home *** CD-ROM | disk | FTP | other *** search
/ ftp.cse.unsw.edu.au / 2014.06.ftp.cse.unsw.edu.au.tar / ftp.cse.unsw.edu.au / pub / doc / papers / misc / cs.toronto.edu:programming / c-news.doc < prev    next >
Encoding:
Text File  |  1992-10-18  |  47.0 KB  |  1,072 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.                    NNNNeeeewwwwssss NNNNeeeeeeeedddd NNNNooootttt BBBBeeee SSSSlllloooowwww
  11.  
  12.  
  13.                        _G_e_o_f_f _C_o_l_l_y_e_r
  14.  
  15.                  _D_e_p_a_r_t_m_e_n_t _o_f _S_t_a_t_i_s_t_i_c_s*
  16.                    _U_n_i_v_e_r_s_i_t_y _o_f _T_o_r_o_n_t_o
  17.                 _u_t_z_o_o!_u_t_c_s_r_i!_u_t_f_r_a_s_e_r!_g_e_o_f_f
  18.  
  19.  
  20.                        _H_e_n_r_y _S_p_e_n_c_e_r
  21.  
  22.                   _Z_o_o_l_o_g_y _C_o_m_p_u_t_e_r _S_y_s_t_e_m_s
  23.                    _U_n_i_v_e_r_s_i_t_y _o_f _T_o_r_o_n_t_o
  24.                         _u_t_z_o_o!_h_e_n_r_y
  25.  
  26.  
  27.                           _A_B_S_T_R_A_C_T
  28.  
  29.           C news is a re-write, from  scratch,  of  the
  30.      `transport layer' of the Usenet software.  C rnews
  31.      runs at over 19 times the  speed  of  B  rnews;  C
  32.      expire runs in minutes rather than the hours taken
  33.      by B expire.  These performance improvements  were
  34.      (mostly)  quite  simple  and  straightforward, and
  35.      they exemplify general principles  of  performance
  36.      tuning.
  37.  
  38.  
  39.  
  40. _1.  _H_i_s_t_o_r_y _a_n_d _M_o_t_i_v_a_t_i_o_n
  41.  
  42.      In the beginning (of Usenet) (1979) was A news, written
  43. at  Duke  University  by Steve Bellovin, Stephen Daniel, Tom
  44. Truscott and others.   A  single  program,  _n_e_w_s,  received,
  45. relayed,  perused  and cleaned out news articles.  All arti-
  46. cles were stored in a single UNIX|- directory, which  made  A
  47. news  suitable  for  local  news  and low volumes of network
  48. news.  News articles were exchanged using a  simple  message
  49. format  in which the first five lines of a message contained
  50. the information  nowadays  found  in  the  article  headers:
  51. unique   article-id,  newsgroup(s),  author,  subject,  date
  52. posted.
  53.  
  54.      As Usenet began to grow (1981), people  in  and  around
  55. the  University  of  California  at Berkeley, including Matt
  56. Glickman and Mark Horton, modified A news extensively.   The
  57. _________________________
  58. * Work done mostly while at U of T Computing Services.
  59. |- UNIX is a registered trademark of AT&T.
  60.  
  61.  
  62.  
  63.  
  64.                        April 18, 1990
  65.  
  66.  
  67.  
  68.  
  69.  
  70.                            - 2 -
  71.  
  72.  
  73. articles of each newsgroup were now  stored  in  a  separate
  74. directory.   The  message  format was changed from the rigid
  75. and inextensible A news header format to one  conforming  to
  76. ARPA  RFC  822  (the  current ARPA mail-message format stan-
  77. dard).  _N_e_w_s was broken into  separate  programs:  _r_e_a_d_n_e_w_s,
  78. _i_n_e_w_s  (aka  _r_n_e_w_s),  and  _e_x_p_i_r_e.   The  authors dubbed the
  79. result ``B news''.  Since the release  of  B  news,  it  has
  80. replaced A news almost|= everywhere on Usenet.
  81.  
  82.      It soon became clear that sending  individual  articles
  83. from  machine  to  machine as separate _u_u_c_p transactions was
  84. unacceptably slow, in part because it  produced  large  _u_u_c_p
  85. spool  directories,  which are searched quite slowly* by the
  86. kernel.  Sites began to _b_a_t_c_h articles into batches of (typ-
  87. ically)  50,000-100,000  bytes  for  transmission  to  other
  88. machines.
  89.  
  90.      At about this time, B news was  changed  to  file  news
  91. articles     in     a     tree,     as     (for     example)
  92. /usr/spool/news/net/women/only/123,    rather    than     as
  93. /usr/spool/news/net.women.only/123.  The motive for this was
  94. primarily elimination of problems with long newsgroup names,
  95. but  shortening directories (and thus speeding searches) was
  96. also a consideration.
  97.  
  98.      As Usenet traffic continued to grow explosively,  sites
  99. began  to  use  data  compression on news batches.  The main
  100. objective was to reduce expensive long-distance phone  time,
  101. but  again  performance  improved a bit: the extra processor
  102. time used for compression and decompression  was  more  than
  103. gained  back by the reduction in processor time used by _u_u_c_p
  104. itself.
  105.  
  106.      Unfortunately, B news has been modified by many  people
  107. since 1981, and has mutated repeatedly to match the changing
  108. nature of Usenet.  It has become complex, slow,  and  diffi-
  109. cult to maintain.
  110.  
  111.      During 1985, we observed that the  nightly  arrival  of
  112. new news and expiry of old news were consuming resources far
  113. out of proportion to the volume of data  involved|-.   _E_x_p_i_r_e
  114. often  ran  for 90 minutes, and _r_n_e_w_s processing averaged 10
  115. seconds or more per article.  Both programs tended to  crip-
  116. ple  systems  by  performing  much  disk i/o and eating much
  117. system-mode CPU time.  _U_t_c_s was running B 2.10.1  news  then
  118. _________________________
  119. |= AT&T Bell Laboratories Research still runs A news for
  120. local newsgroups.
  121. * Recent _u_u_c_ps (notably  Honey  DanBer)  provide  spool
  122. sub-directories,  and  recent  4BSD  (4.3BSD and later)
  123. kernels  provide  linear  (as  opposed  to   quadratic)
  124. directory searching, both of which help this problem.
  125. |- Never mind the cost/benefit ratio.
  126.  
  127.  
  128.  
  129.  
  130.                        April 18, 1990
  131.  
  132.  
  133.  
  134.  
  135.  
  136.                            - 3 -
  137.  
  138.  
  139. and _u_t_z_o_o was running B 2.10 news.  Although  newer  B  news
  140. releases  were available, they offered little beyond B 2.10,
  141. and it was often necessary to  regression-test  new  B  news
  142. releases to verify that reported, published bug fixes had in
  143. fact been applied.
  144.  
  145.      Spencer acted first and rewrote _e_x_p_i_r_e from the  ground
  146. up.   Though  it  initially  lacked  any  form  of selective
  147. expiry, this _e_x_p_i_r_e, when run each night, finished in  about
  148. 15  minutes.   (This  was  on 750-class machines holding all
  149. Usenet news and expiring after 14 days.)
  150.  
  151.      Collyer observed in November 1985 that  B  _r_n_e_w_s,  upon
  152. receiving  a  batch  of  news,  immediately _e_x_e_ced a trivial
  153. unbatcher which copied each article into  a  temporary  file
  154. and  then forked and _e_x_e_ced B rnews again.  Such a technique
  155. is clearly overkill for articles averaging about 3,000 bytes
  156. each.   Preliminary experiments failed to produce a modified
  157. B rnews that could unravel a batch without forking.  Consul-
  158. tation  with  Rick  Adams,  the  current  B-news maintainer,
  159. revealed that this same technique remained in the upcoming B
  160. news  release  (variously  B  2.10.3 or B 2.11).  Within one
  161. week|=, a from-scratch C _r_n_e_w_s  prototype  was  working  well
  162. enough to run experimentally on a `leaf' machine receiving a
  163. subset of news.
  164.  
  165.      This prototype version lacked  a  good  many  necessary
  166. amenities, and over the next eight months it was enhanced to
  167. bring it up  to  full  functionality.   It  was  also  tuned
  168. heavily to improve its performance, since it was faster than
  169. B _r_n_e_w_s but still not fast enough to make us happy.
  170.  
  171.      Once the _r_n_e_w_s newsgroup name  matching  routines  were
  172. working,  Spencer  revised  _e_x_p_i_r_e  to add selective expiry,
  173. specified in a control file.  Recently, we have also revised
  174. our  old batcher heavily, largely to add capability but with
  175. an eye on performance.
  176.  
  177. _2.  _R_n_e_w_s _P_e_r_f_o_r_m_a_n_c_e
  178.  
  179.      The basic objective of C  news  was  simpler  code  and
  180. higher  performance.   This  may  sound trite, but note that
  181. performance was an explicit objective.  That was  important.
  182. _P_r_o_g_r_a_m_s _w_i_l_l _s_e_l_d_o_m _r_u_n _f_a_s_t_e_r _u_n_l_e_s_s _y_o_u _c_a_r_e _a_b_o_u_t _m_a_k_i_n_g
  183. _t_h_e_m _r_u_n _f_a_s_t_e_r.
  184.  
  185.      `Faster' implies comparison to a slower version.  Know-
  186. ing  the  value of improvements, and assessing this in rela-
  187. tion to their cost, requires knowing the performance of  the
  188. unimproved  version.   Collyer  kept detailed records of his
  189. work on _r_n_e_w_s, so he could see  how  much  progress  he  was
  190. _________________________
  191. |= 40 hours, Collyer didn't have to work hard.
  192.  
  193.  
  194.  
  195.  
  196.                        April 18, 1990
  197.  
  198.  
  199.  
  200.  
  201.  
  202.                            - 4 -
  203.  
  204.  
  205. making.  See the Appendix for the final result.  _T_o _k_n_o_w _h_o_w
  206. _t_o _g_e_t _s_o_m_e_w_h_e_r_e, _y_o_u _m_u_s_t _k_n_o_w _w_h_e_r_e _y_o_u _a_r_e _s_t_a_r_t_i_n_g _f_r_o_m.
  207.  
  208.      The first functional C _r_n_e_w_s ran at about 3  times  the
  209. speed  of  B  _r_n_e_w_s.  We had assumed that merely eliminating
  210. the fork/exec on each article would  give  a  factor  of  10
  211. improvement,  so  this  was disappointing.  _A_v_o_i_d_i_n_g _o_b_v_i_o_u_s
  212. _p_e_r_f_o_r_m_a_n_c_e _d_i_s_a_s_t_e_r_s _h_e_l_p_s...  _b_u_t _i_t'_s _n_o_t _a_l_w_a_y_s _e_n_o_u_g_h.
  213.  
  214.      Profiling, first with _p_r_o_f(1) and later  with  4.2BSD's
  215. _g_p_r_o_f(1),  and rewriting of the bottlenecks thus discovered,
  216. eventually brought the speed up to over 19 times  the  speed
  217. of  B _r_n_e_w_s.  This required a number of write-profile-study-
  218. rewrite cycles.  There is undoubtedly still a  lot  of  code
  219. which  could be faster than it is, but since profiling shows
  220. that it doesn't have a significant impact on overall perfor-
  221. mance,  who  cares?   _T_o  _l_o_c_a_t_e  _p_e_r_f_o_r_m_a_n_c_e _p_r_o_b_l_e_m_s, _l_o_o_k
  222. _t_h_r_o_u_g_h _t_h_e _e_y_e_s _o_f _t_h_y _p_r_o_f_i_l_e_r.
  223.  
  224.      Collyer first experimented with using  _r_e_a_d  and  _w_r_i_t_e
  225. system calls instead of _f_r_e_a_d and _f_w_r_i_t_e, and got a substan-
  226. tial saving.  Though the  usage  of  system  calls  in  this
  227. experiment was unportable, the saving eventually lead him to
  228. rewrite _f_r_e_a_d and _f_w_r_i_t_e from scratch to reduce the per-byte
  229. overheads.  This helped noticeably, since pre-System-V _f_r_e_a_d
  230. and _f_w_r_i_t_e are really quite  inefficient.   _I_f  _t_h_y  _l_i_b_r_a_r_y
  231. _f_u_n_c_t_i_o_n _o_f_f_e_n_d_s _t_h_e_e, _p_l_u_c_k _i_t _o_u_t _a_n_d _f_i_x _i_t.
  232.  
  233.      At the time, C _r_n_e_w_s was doing fairly fine-grain  lock-
  234. ing,  essentially  locking  each  file independently on each
  235. use.  News doesn't need the resulting potential concurrency,
  236. especially when _r_n_e_w_s runs relatively quickly, and the lock-
  237. ing was clearly a  substantial  fraction  of  the  execution
  238. time.  C _r_n_e_w_s was changed to use B-news compatible locking,
  239. with a single lock for the news system as a whole.   _S_i_m_p_l_i_-
  240. _c_i_t_y _a_n_d _s_p_e_e_d _o_f_t_e_n _g_o _t_o_g_e_t_h_e_r.
  241.  
  242.      When sending articles to a site using  batching,  _r_n_e_w_s
  243. just  appends  the  filename of each article to a _b_a_t_c_h _f_i_l_e
  244. for that site.  The batch file is  later  processed  by  the
  245. batcher.  In principle, batching is an option, and different
  246. sites may get different sets of  newsgroups.   In  practice,
  247. few  articles  are ever sent unbatched, and most articles go
  248. to all sites fed by a given system.  This means  that  _r_n_e_w_s
  249. is  repeatedly  appending  lines  to  the  same set of batch
  250. files.  Noticing this, Collyer changed C _r_n_e_w_s to keep these
  251. files open, rather than re-opening them for every  article*.
  252. _O_n_c_e _y_o_u'_v_e _g_o_t _i_t, _h_a_n_g _o_n_t_o _i_t.
  253. _________________________
  254. * The price for this tactic is that the code has to  be
  255. prepared  for  the possibility that the number of sites
  256. being fed  exceeds  the  supply  of  file  descriptors.
  257. Fortunately, that is rare.
  258.  
  259.  
  260.  
  261.  
  262.                        April 18, 1990
  263.  
  264.  
  265.  
  266.  
  267.  
  268.                            - 5 -
  269.  
  270.  
  271.      These two simple changes-coarser locking and  retaining
  272. open  files-cut  system  time  by about 20% and real time by
  273. still more.
  274.  
  275.      On return from Christmas holidays,  after  considerable
  276. agonizing  over  performance  issues,  Collyer  turned  some
  277. small, heavily-used character-handling functions  into  mac-
  278. ros.   This  reduced user-mode time quite a bit.  _A _f_u_n_c_t_i_o_n
  279. _c_a_l_l _i_s _a_n _e_x_p_e_n_s_i_v_e _w_a_y _t_o _p_e_r_f_o_r_m _a _s_m_a_l_l, _q_u_i_c_k _t_a_s_k.
  280.  
  281.      _R_n_e_w_s was always looking up files  by  full  pathnames.
  282. Changing  it  to  _c_h_d_i_r  to the right place and use relative
  283. names thereafter reduced system time  substantially.   _A_b_s_o_-
  284. _l_u_t_e _p_a_t_h_n_a_m_e_s _a_r_e _c_o_n_v_e_n_i_e_n_t _b_u_t _n_o_t _c_h_e_a_p.
  285.  
  286.      Studying the profiling data  revealed  that  _r_n_e_w_s  was
  287. spending  a  lot of time re-re-re-reading the _s_y_s and _a_c_t_i_v_e
  288. files.  These files are needed for processing every article,
  289. and  they  are  not large.  Collyer modified _r_n_e_w_s to simply
  290. read these files in once and keep them in core.  This change
  291. alone  cut system time and real time by roughly 30%.  _A_g_a_i_n,
  292. _o_n_c_e _y_o_u'_v_e _g_o_t _i_t, _d_o_n'_t _t_h_r_o_w _i_t _a_w_a_y!
  293.  
  294.      There is a more subtle point here, as well.  When these
  295. files were re-read every time, they were generally processed
  296. a line at a time.  The revised strategy was to _s_t_a_t the file
  297. to  determine  its  size,  _m_a_l_l_o_c enough space for the whole
  298. file, and bring it in with a single _r_e_a_d.  This is a  vastly
  299. more  efficient way to read a file!  _T_a_s_k_s _w_h_i_c_h _c_a_n _b_e _d_o_n_e
  300. _i_n _o_n_e _o_p_e_r_a_t_i_o_n _s_h_o_u_l_d _b_e.
  301.  
  302.      At this point (mid-January 1986), C  _r_n_e_w_s  was  faster
  303. than  B  _r_n_e_w_s by one order of magnitude, and there was much
  304. rejoicing.
  305.  
  306.      In principle, the `Newsgroups:' header line,  determin-
  307. ing  what  directories  the article will be filed in, can be
  308. arbitrarily far from the start of the article.  In practice,
  309. it is almost always found within the first thousand bytes or
  310. so.  By complicating rnews substantially, it became possible
  311. in  most  cases to _c_r_e_a_t the file in the right place (or the
  312. first of the right places) in /_u_s_r/_s_p_o_o_l/_n_e_w_s before writing
  313. any  of  the  article to disk, eliminating the need for tem-
  314. porary files or even temporary links.   The  improvement  in
  315. system time was noticeable, and the improvement in user time
  316. was even more noticeable.  _P_r_e_p_a_r_e _f_o_r _t_h_e _w_o_r_s_t  _c_a_s_e,  _b_u_t
  317. _o_p_t_i_m_i_z_e _f_o_r _t_h_e _t_y_p_i_c_a_l _c_a_s_e.
  318.  
  319.      There  are  certain  circumstances,  notably   control-
  320. message  articles,  in  which it is necessary to re-read the
  321. article after filing it.   _R_n_e_w_s  originally  re-opened  the
  322. article to permit this.  Changing the invocation of _f_o_p_e_n to
  323. use the wwww++++ mode made it possible to just seek  back  to  the
  324. beginning  instead,  which  is _m_u_c_h faster.  This, plus some
  325.  
  326.  
  327.  
  328.                        April 18, 1990
  329.  
  330.  
  331.  
  332.  
  333.  
  334.                            - 6 -
  335.  
  336.  
  337. similar  elimination  of  other  redundant  calls  to  _o_p_e_n,
  338. reduced  system  time  by  over 30%.  _G_e_t _a_s _m_u_c_h _m_i_l_e_a_g_e _a_s
  339. _p_o_s_s_i_b_l_e _o_u_t _o_f _e_a_c_h _c_a_l_l _t_o _t_h_e _k_e_r_n_e_l.
  340.  
  341.      Both scanning the in-core _a_c_t_i_v_e and _s_y_s files and  re-
  342. writing  the  _a_c_t_i_v_e  file are simpler if the in-core copies
  343. are kept exactly as on disk, but this implied frequent scans
  344. to locate the ends of lines.  It turned out to be worthwhile
  345. to  pre-scan  the  _a_c_t_i_v_e  file  for  line  boundaries,  and
  346. remember them.  _W_h_e_n _s_t_o_r_i_n_g _f_i_l_e_s _i_n _a_n _u_n_s_t_r_u_c_t_u_r_e_d _w_a_y, _a
  347. _l_i_t_t_l_e _r_e_m_e_m_b_e_r_e_d _i_n_f_o_r_m_a_t_i_o_n _a_b_o_u_t _t_h_e_i_r _s_t_r_u_c_t_u_r_e  _g_o_e_s  _a
  348. _l_o_n_g _w_a_y _i_n _s_p_e_e_d_i_n_g _u_p _a_c_c_e_s_s.
  349.  
  350.      We already had a _S_T_R_E_Q macro, just a simple  invocation
  351. of  _s_t_r_c_m_p,  as  a  convenience.   As a result of some other
  352. experience by Spencer, Collyer tried replacing some calls of
  353. _s_t_r_n_c_m_p  by a _S_T_R_E_Q_N macro, which compared the first charac-
  354. ter of the two strings in-line before incurring the overhead
  355. of  calling  _s_t_r_n_c_m_p.   This  sped things up noticeably, and
  356. later got propagated through more  and  more  of  the  code.
  357. String-equality tests usually fail on the very first charac-
  358. ter.  _T_e_s_t _t_h_e _w_a_t_e_r _b_e_f_o_r_e _t_a_k_i_n_g _t_h_e _p_l_u_n_g_e.
  359.  
  360.      While looking at string functions, Collyer noticed that
  361. _s_t_r_n_c_m_ps to determine whether a line was a particular header
  362. line had the comparison length computed by  applying  _s_t_r_l_e_n
  363. to  the  prototype  header.   With a little bit of work, the
  364. prototypes were isolated as individual character arrays ini-
  365. tialized  at  compile time.  This permitted substituting the
  366. compile-time _s_i_z_e_o_f operation for the run-time _s_t_r_l_e_n.   _L_e_t
  367. _t_h_e _c_o_m_p_i_l_e_r _d_o _t_h_e _w_o_r_k _w_h_e_n _p_o_s_s_i_b_l_e.
  368.  
  369.      At this point, profiling was turned off temporarily for
  370. speed  tests.   Profiling  does  impose  some overhead.  The
  371. speed trials showed that C _r_n_e_w_s was now running at over  15
  372. times the speed of B _r_n_e_w_s.
  373.  
  374.      After months of adding frills, bunting and B 2.11  com-
  375. patibility*, Collyer again returned to performance tuning in
  376. August  1986.   The  4.2BSD  kernel on _u_t_c_s now included the
  377. 4.3BSD _n_a_m_e_i caches, which improve  filename-lookup  perfor-
  378. mance  considerably.  Unfortunately, considerations of crash
  379. recovery dictated some loss in performance: it seemed desir-
  380. able to put batch-file additions out by the line rather than
  381. by the block.  _P_e_r_f_o_r_m_a_n_c_e _i_s _n_o_t _e_v_e_r_y_t_h_i_n_g.
  382.  
  383.      _G_p_r_o_f revealed that  newsgroup  name  matching  was  an
  384. unexpected   bottleneck,  so  that  module  was  extensively
  385. tweaked by adding _r_e_g_i_s_t_e_r declarations,  turning  functions
  386. _________________________
  387. * And supposed  B  2.11  compatibility,  as  those  who
  388. remember  the  short-lived  cross-posting  restrictions
  389. will recall.
  390.  
  391.  
  392.  
  393.  
  394.                        April 18, 1990
  395.  
  396.  
  397.  
  398.  
  399.  
  400.                            - 7 -
  401.  
  402.  
  403. into macros, applying _S_T_R_E_Q_N and such more widely, and  gen-
  404. erally  tuning  the  details of string operations.  The code
  405. that handled _s_y_s-file lines got similar treatment next.  The
  406. combination  cut  40% off user-mode time.  _P_e_r_s_i_s_t_e_n_t _t_u_n_i_n_g
  407. _o_f _k_e_y _m_o_d_u_l_e_s _c_a_n _y_i_e_l_d _l_a_r_g_e _b_e_n_e_f_i_t_s.
  408.  
  409.      Newsgroup matching remained moderately costly,  and  an
  410. investigation  of  where  it  was  being  used  revealed two
  411. separate tests for a particular special form  of  name.   It
  412. proved  awkward  to  combine the two, so the testing routine
  413. was changed to remember having  done  that  particular  test
  414. already.  _I_f _t_h_e _s_a_m_e _q_u_e_s_t_i_o_n _i_s _a_s_k_e_d _r_e_p_e_a_t_e_d_l_y, _m_e_m_o_r_i_z_e
  415. _t_h_e _a_n_s_w_e_r.
  416.  
  417.      By this time, the number of system calls needed to pro-
  418. cess a single article could be counted on one's fingers, and
  419. their individual contributions could be  assessed.   At  one
  420. point  it  was  desirable  for  a  _c_r_e_a_t to fail if the file
  421. already existed, so this was being checked with  a  call  to
  422. _a_c_c_e_s_s first.  John Gilmore pointed out that on systems with
  423. a 3-argument _o_p_e_n (4.2BSD,  System  V),  this  test  can  be
  424. folded   into  the  _o_p_e_n.   The  elimination  of  the  extra
  425. name->file (_n_a_m_e_i) mapping cut both  system  time  and  real
  426. time by another 15%.  (Note that this system _d_o_e_s have _n_a_m_e_i
  427. cacheing!)  _F_i_l_e _n_a_m_e _l_o_o_k_u_p_s _a_r_e _e_x_p_e_n_s_i_v_e; _m_i_n_i_m_i_z_e _t_h_e_m.
  428.  
  429.      The development system (uuuuttttccccssss, a 750) is now filing  2-3
  430. articles  per  second on average; _u_t_f_r_a_s_e_r (a Sun 3/160 with
  431. an Eagle disk) is typically filing 6-7 articles per  second.
  432. C  _r_n_e_w_s runs over 19 times as fast in real time as B _r_n_e_w_s,
  433. over 25 times as fast in system-mode CPU time,  roughly  3.6
  434. times  as  fast  in user-mode CPU time, and over 10 times as
  435. fast in combined CPU times.
  436.  
  437.      With one exception  (see  _F_u_t_u_r_e  _D_i_r_e_c_t_i_o_n_s),  it  now
  438. appears  that  very  little  can  be  done to speed up _r_n_e_w_s
  439. without changing the specifications.  It seems to be execut-
  440. ing  nearly  the bare minimum of system calls, and the user-
  441. level code has been hand-optimised fairly heavily.
  442.  
  443. _3.  _E_x_p_i_r_e _P_e_r_f_o_r_m_a_n_c_e
  444.  
  445.      The rewrite of _e_x_p_i_r_e that started  this  whole  effort
  446. was  only partly motivated by performance problems.  Perfor-
  447. mance was definitely bad enough to  require  attention,  but
  448. the B _e_x_p_i_r_e of the time also had some serious bugs.  Worse,
  449. the code was a terrible mess and was  almost  impossible  to
  450. understand,  never  mind  fix.   Early efforts were directed
  451. mainly at producing a version  that  would  _w_o_r_k;  rewriting
  452. _e_x_p_i_r_e  from  scratch  simply looked like the easiest route.
  453. Decisions made along the way,  largely  for  other  reasons,
  454. nevertheless produced major speedups.
  455.  
  456.      The first of these decisions was  a  reduction  in  the
  457.  
  458.  
  459.  
  460.                        April 18, 1990
  461.  
  462.  
  463.  
  464.  
  465.  
  466.                            - 8 -
  467.  
  468.  
  469. scope  of  the  program.   B  _e_x_p_i_r_e had several options for
  470. doing quite unrelated tasks, such as rebuilding news's  his-
  471. tory file.  The code for these functions was substantial and
  472. was somewhat interwoven with the  rest.   C  _e_x_p_i_r_e  adheres
  473. closely  to a central tenet of the `Unix Philosophy': _a _p_r_o_-
  474. _g_r_a_m _s_h_o_u_l_d _d_o _o_n_e _t_a_s_k, _a_n_d _d_o _i_t _w_e_l_l.   This  may  appear
  475. unrelated  to  performance, but better-focussed programs are
  476. generally simpler and smaller, reducing their resource  con-
  477. sumption  and  making  performance  tuning easier (and hence
  478. more likely).  In addition, a  multipurpose  program  almost
  479. always pays some performance penalty for its generality.
  480.  
  481.      The second significant decision had the biggest  effect
  482. on  performance,  despite  being  made for totally unrelated
  483. reasons.  For each news article, the  B  news  history  file
  484. contained  the  arrival date and an indication of what news-
  485. groups it was in.  This is _a_l_m_o_s_t all the  information  that
  486. _e_x_p_i_r_e  needs to decide whether to expire an article or not.
  487. The missing* data is whether the article contains an  expli-
  488. cit expiry date, and if so, what it is.   B  _e_x_p_i_r_e  had  to
  489. discover this for itself, which required opening the article
  490. and parsing its headers.  A site which retains news for  two
  491. weeks  will  have  upwards of 5,000 articles on file.  A few
  492. dozen of them will have explicit expiry dates.  _B_u_t _B _e_x_p_i_r_e
  493. _o_p_e_n_e_d  _a_n_d  _s_c_a_n_n_e_d  _a_l_l _5,_0_0_0+ _a_r_t_i_c_l_e_s _e_v_e_r_y _t_i_m_e _i_t _r_a_n!
  494. This was a performance disaster.
  495.  
  496.      We actually did not want to parse headers in _e_x_p_i_r_e  at
  497. all,  because  the  B  news header-parsing code was (and is)
  498. complex and was known to contain major  bugs.   The  perfor-
  499. mance  implications of this were obvious, although secondary
  500. at the time.  Header parsing is itself a  non-trivial  task,
  501. and  accessing  5,000+  files  simply  cannot be made cheap.
  502. _I_n_f_o_r_m_a_t_i_o_n _n_e_e_d_e_d _c_e_n_t_r_a_l_l_y _s_h_o_u_l_d _b_e _k_e_p_t _c_e_n_t_r_a_l_l_y.
  503.  
  504.      The C news history file has the same format as that  of
  505. B  news,  with  one addition: a field recording the explicit
  506. expiry date, if any, of each article.  If no expiry date  is
  507. present  in  the article, the field contains `-' as a place-
  508. marker|-.  In this way, the header parsing is done  _o_n_c_e  per
  509. _________________________
  510. * Recent versions of B news have made some  attempt  to
  511. redress this lack, but haven't gone as far as C expire.
  512. The discussion here applies to the B  expire  that  was
  513. current at the time C expire was written.
  514. |- It would be possible to simply compute  a  definitive
  515. expiry  date for an article when it arrives, and record
  516. that.   This  would   eliminate   the   decision-making
  517. overhead in _e_x_p_i_r_e, but would greatly slow the response
  518. to changes in  expiry  policy.   Since  one  reason  to
  519. change policy is time-critical problems like a shortage
  520. of disk space, this  loss  of  flexibility  was  judged
  521. unacceptable.    It  is  better  to  leave  the  expiry
  522. decision to _e_x_p_i_r_e and concentrate on making _e_x_p_i_r_e  do
  523.  
  524.  
  525.  
  526.                        April 18, 1990
  527.  
  528.  
  529.  
  530.  
  531.  
  532.                            - 9 -
  533.  
  534.  
  535. article, on arrival.  In fact, the extra effort involved  is
  536. essentially  nil,  since  _r_n_e_w_s  does full header parsing at
  537. arrival time anyway.  _R_n_e_w_s had to be changed to  write  out
  538. the  expiry date, and code which knew the format of the his-
  539. tory file had to be changed to know about the  extra  field.
  540. Perhaps a dozen lines of code outside _e_x_p_i_r_e were involved.
  541.  
  542.      A crude first version of C _e_x_p_i_r_e, incorporating  these
  543. decisions in the most minimal way, ran an order of magnitude
  544. faster than B _e_x_p_i_r_e.  Precise timing comparisons  were  not
  545. practical  at  the  time,  since  the  original motive for C
  546. _e_x_p_i_r_e was that B _e_x_p_i_r_e  had  stopped  working  completely,
  547. crippled by bugs in its header parsing.  Later versions of B
  548. _e_x_p_i_r_e  did  cure  this  problem,  but  we  were  no  longer
  549. interested  in  putting up slow, buggy software just to make
  550. an accurate comparison.
  551.  
  552.      Further work on C _e_x_p_i_r_e mostly concentrated on  clean-
  553. ing up the hasty first version, and on incorporating desired
  554. features such as selective expiry by  newsgroup.   Selective
  555. expiry  caused  a  small  loss  in  performance by requiring
  556. _e_x_p_i_r_e to check the newsgroup(s) of each article against  an
  557. expiry-control  list.  Here, _e_x_p_i_r_e benefitted from the work
  558. done to speed up the newsgroup-matching primitives of _r_n_e_w_s,
  559. since  _e_x_p_i_r_e  uses the same routines.  _I_f _y_o_u _r_e-_i_n_v_e_n_t _t_h_e
  560. _s_q_u_a_r_e _w_h_e_e_l, _y_o_u _w_i_l_l _n_o_t _b_e_n_e_f_i_t _w_h_e_n _s_o_m_e_b_o_d_y _e_l_s_e _r_o_u_n_d_s
  561. _o_f_f _t_h_e _c_o_r_n_e_r_s|=.
  562.  
  563.      One improvement that was made late in  development  was
  564. in  the  format  of the dates stored in the history file.  B
  565. _r_n_e_w_s stored the arrival date in  human-readable  form,  and
  566. _e_x_p_i_r_e  converted  this into numeric form for comparisons of
  567. dates.  Date conversion is  a  complex  operation,  and  the
  568. widely-distributed  _g_e_t_d_a_t_e  function  used  by  news is not
  569. fast.  Inspection of the code established  that  _e_x_p_i_r_e  was
  570. the  only  program that ever looked at the dates in the his-
  571. tory file.  There is some potential use of  the  information
  572. for  debugging,  but this is infrequent, and a small program
  573. that converts decimal numeric dates to  human-readable  ones
  574. addresses  the  issue.   Both C _r_n_e_w_s and C _e_x_p_i_r_e now store
  575. the dates in decimal numeric  form.   _S_t_o_r_e  _r_e_p_e_a_t_e_d_l_y-_u_s_e_d
  576. _i_n_f_o_r_m_a_t_i_o_n _i_n _a _f_o_r_m _t_h_a_t _a_v_o_i_d_s _e_x_p_e_n_s_i_v_e _c_o_n_v_e_r_s_i_o_n_s.
  577.  
  578.      Actually, C _e_x_p_i_r_e bows to compatibility  by  accepting
  579. either  form  on input, but outputs only the decimal form as
  580. it regenerates the history file.  Thus, in the  worst  case,
  581. _e_x_p_i_r_e  does the conversion only once for each history line,
  582. rather than once per line per run.  ``_I_f  _t_h_e_y  _h_a_n_d  _y_o_u  _a
  583. _l_e_m_o_n, _m_a_k_e _l_e_m_o_n_a_d_e''.
  584. _________________________
  585. it quickly.
  586. |=  A corollary of this is:  _k_n_o_w _t_h_y _l_i_b_r_a_r_i_e_s, _a_n_d _u_s_e
  587. _t_h_e_m.
  588.  
  589.  
  590.  
  591.  
  592.                        April 18, 1990
  593.  
  594.  
  595.  
  596.  
  597.  
  598.                            - 10 -
  599.  
  600.  
  601.      If _e_x_p_i_r_e is archiving expired articles, it may need to
  602. create  directories  to  hold  them.   This is an inherently
  603. expensive operation, but it is  infrequently  needed.   How-
  604. ever,  checking  to see whether it _i_s in fact needed is also
  605. somewhat expensive... and the answer is almost always  `no'.
  606. The  same  is  true  of checking to see whether the original
  607. article really still exists:  it almost always does.   (This
  608. cannot  be  subsumed  under generic `archiving failed' error
  609. handling because a missing original is just an article  that
  610. was  cancelled,  and  does  not  call for a trouble report.)
  611. Accordingly, C _e_x_p_i_r_e just charges ahead and attempts to  do
  612. the  copying.   Only  if  this fails does _e_x_p_i_r_e analyze the
  613. situation in detail.  _C_a_r_r_y_i_n_g _a _n_e_t _i_n _f_r_o_n_t _o_f _y_o_u _i_n _c_a_s_e
  614. _y_o_u _t_r_i_p _i_s _u_s_u_a_l_l_y _w_a_s_t_e_d _e_f_f_o_r_t.
  615.  
  616.      Archiving  expired  articles  often  requires   copying
  617. across  filesystem  boundaries,  since  it's not uncommon to
  618. give current news and archived news rather different  treat-
  619. ment  for  space  allocation  and backups.  Copying from one
  620. filesystem to another can involve major disk  head  movement
  621. if  the two filesystems are on the same spindle.  Since head
  622. movement is expensive, maximizing performance requires  get-
  623. ting as much use as possible out of each movement*.   _E_x_p_i_r_e
  624. is  not  a large program, and even on a small machine it can
  625. spare the space for a large copying buffer.  So it does  its
  626. archiving  copy  operations  using an 8KB buffer.  _B_u_y_i_n_g _i_n
  627. _b_u_l_k _i_s _o_f_t_e_n _c_h_e_a_p_e_r.  Since  8KB  accommodates  most  news
  628. articles  in one gulp, there is little point in enlarging it
  629. further.  _T_h_e _l_a_w _o_f _d_i_m_i_n_i_s_h_i_n_g _r_e_t_u_r_n_s _d_o_e_s _a_p_p_l_y _t_o  _b_u_y_-
  630. _i_n_g _i_n _b_u_l_k.
  631.  
  632.      Since _e_x_p_i_r_e  is  operating  on  the  history  file  at
  633. (potentially)  the same time that _r_n_e_w_s is adding more arti-
  634. cles to it, some form of locking is necessary.   Given  that
  635. _e_x_p_i_r_e has to look over the whole database of news, and typ-
  636. ically has to expire a modest fraction of the  articles,  it
  637. is  a  relatively  long-running  process  compared to _r_n_e_w_s.
  638. Contention for the history-file lock  can  be  minimized  by
  639. noting  that  _r_n_e_w_s never does anything other than append to
  640. the file.  So _e_x_p_i_r_e can leave the file unlocked while scan-
  641. ning it; the contents will not change.  When (and only when)
  642. _e_x_p_i_r_e reaches end-of-file, it locks the news system, checks
  643. for  and  handles any further entries arriving on the end of
  644. the history file meanwhile, and finishes up.   _L_o_c_k_i_n_g  _d_a_t_a
  645. _t_h_a_t _w_o_n'_t _c_h_a_n_g_e _i_s _w_a_s_t_e_f_u_l.
  646.  
  647.      After careful application  of  these  various  improve-
  648. ments,  C  _e_x_p_i_r_e is fast enough that further speedup is not
  649. worth much effort.  However, an analysis of where it  spends
  650. _________________________
  651. * As witness the  progressive  increase  in  filesystem
  652. block size that produced major performance improvements
  653. in successive versions of 4BSD.
  654.  
  655.  
  656.  
  657.  
  658.                        April 18, 1990
  659.  
  660.  
  661.  
  662.  
  663.  
  664.                            - 11 -
  665.  
  666.  
  667. its time does suggest one area that might merit attention in
  668. the future.  _E_x_p_i_r_e rebuilds the history file to reflect the
  669. removal of expired articles.  The  history  file  is  large.
  670. _E_x_p_i_r_e  must  also rebuild the _d_b_m indexing data base, since
  671. it contains offsets into the history file.  This  data  base
  672. is  comparable  in  size  to the history file itself, and is
  673. generated in a less orderly manner that requires  more  disk
  674. accesses.
  675.  
  676.      Much of the time needed for these operations  could  be
  677. eliminated  if _e_x_p_i_r_e could mark a history line as `expired'
  678. without changing its size.  This could be  done  by  writing
  679. into  the  history  file rather than by rebuilding the whole
  680. file, and the indexing database would not  need  alteration.
  681. This  would also permit retaining information about an arti-
  682. cle after the article itself expires, which  would  simplify
  683. rejecting  articles  that  arrive again (due to loops in the
  684. network, etc.) after the original has expired.  The  history
  685. file  should still be cleaned out, and the indexing database
  686. rebuilt, occasionally.  C _e_x_p_i_r_e contains  some  preliminary
  687. `hooks'  for  this approach, but to date full implementation
  688. does not seem justified:  C _e_x_p_i_r_e is already  fast  enough.
  689. _K_n_o_w _w_h_e_n _y_o_u _a_r_e _f_i_n_i_s_h_e_d.
  690.  
  691. _4.  _B_a_t_c_h_e_r _P_e_r_f_o_r_m_a_n_c_e
  692.  
  693.      The C batcher is descended  from  a  very  old  version
  694. written to add some minor functionality that was not present
  695. in the B batcher of the time.  It is small and  straightfor-
  696. ward,  and  contains only a couple of noteworthy performance
  697. hacks.
  698.  
  699.      The batcher works from a list of filed articles, to  be
  700. composed  into  batches.   The list is by absolute pathname.
  701. All of these files reside in the same area of  the  system's
  702. directory  tree,  and  referring to them with absolute path-
  703. names every time implies repeatedly traversing the same ini-
  704. tial  pathname prefix.  To avoid this, the batcher initially
  705. _c_h_d_i_rs to a likely-looking place  such  as  /_u_s_r/_s_p_o_o_l/_n_e_w_s.
  706. Thereafter,  before  using  an  absolute pathname to open an
  707. article, it checks whether the beginning of the pathname  is
  708. identical to the directory where it already resides.  If so,
  709. it strips this prefix off the name  before  proceeding.   _I_f
  710. _y_o_u  _w_a_l_k  _t_h_e  _s_a_m_e _r_o_a_d _r_e_p_e_a_t_e_d_l_y, _c_o_n_s_i_d_e_r _m_o_v_i_n_g _t_o _t_h_e
  711. _o_t_h_e_r _e_n_d.
  712.  
  713.      The batcher's input is usually in fairly random  order,
  714. with  little tendency for successive files to be in the same
  715. directory.   If  this  were  not  the  case,  it  would   be
  716. worthwhile  for  the  batcher to actually move around in the
  717. directory tree to be closer to the next file.
  718.  
  719.      The batcher used to copy data using _p_u_t_c(_g_e_t_c()) loops.
  720. This   has   been   replaced   by   _f_r_e_a_d/_f_w_r_i_t_e   which  is
  721.  
  722.  
  723.  
  724.                        April 18, 1990
  725.  
  726.  
  727.  
  728.  
  729.  
  730.                            - 12 -
  731.  
  732.  
  733. significantly faster,  especially  if  using  the  souped-up
  734. _f_r_e_a_d/_f_w_r_i_t_e mentioned earlier.  _I_f _y_o_u _n_e_e_d _t_o _m_o_v_e _a _m_o_u_n_-
  735. _t_a_i_n, _u_s_e _a _b_u_l_l_d_o_z_e_r, _n_o_t _a _t_e_a_s_p_o_o_n.
  736.  
  737. _5.  _F_u_t_u_r_e _D_i_r_e_c_t_i_o_n_s
  738.  
  739.      The one improvement we are still considering for  _r_n_e_w_s
  740. is  a  radical  revision of the newsgroup-matching strategy.
  741. Newsgroup matching still consumes  about  18%  of  user-mode
  742. processor time.  The key observation is that the information
  743. that determines which newsgroups go to  which  sites  seldom
  744. changes.   It  would  probably  be  worth precompiling a bit
  745. array indexed by newsgroup and site, and recompiling it only
  746. when  the  _a_c_t_i_v_e file or the _s_y_s file changes in a relevant
  747. way.  This would cut the newsgroup-matching time  to  essen-
  748. tially zero.
  749.  
  750.      _R_n_e_w_s would be faster (and  simpler)  if  `Newsgroups:'
  751. and `Control:' were required to be the first two headers (if
  752. present) of each article.  At present _r_n_e_w_s  tries  to  find
  753. them  before  starting  to write the article out, so that it
  754. can put the article in the right place from the  start,  but
  755. it  has  to  allow  for the possibility that vast volumes of
  756. other headers may precede them.
  757.  
  758.      Hashing _a_c_t_i_v_e-file lookups in _r_n_e_w_s would be fun,  but
  759. profiling  suggests  that  it's  not  worthwhile  unless the
  760. number of newsgroups is in the thousands.
  761.  
  762.      When PDP-11's are truly dead  on  Usenet,  the  use  of
  763. large  per-process  memories  _m_a_y  allow further speedups to
  764. _r_n_e_w_s by reading the entire batch into memory  at  once  and
  765. writing  each  article  to  disk  in  a few _w_r_i_t_e_s (it can't
  766. easily be reduced to a single _w_r_i_t_e because headers must  be
  767. modified before filing).
  768.  
  769.      One optimization we have _n_o_t  considered  is  re-coding
  770. key  parts  in  assembler.  C news already runs on five dif-
  771. ferent types of  machine.   Use  of  assembler  would  be  a
  772. maintenance nightmare, and probably would not yield benefits
  773. comparable to those of the more high-level changes.
  774.  
  775. _6.  _A_c_k_n_o_w_l_e_d_g_e_m_e_n_t_s
  776.  
  777.      Ian Darwin ran the  very  earliest  alpha  versions  of
  778. _r_n_e_w_s  and  gave  helpful feedback.  Mike Ghesquiere, Dennis
  779. Ferguson and others have run later versions and prodded Col-
  780. lyer  to fix or implement assorted things.  John Gilmore and
  781. Laura Creighton read and criticized an early  alpha  version
  782. of _r_n_e_w_s.
  783.  
  784. _7.  _A_p_p_e_n_d_i_x:  _r_n_e_w_s _T_i_m_e_s
  785.  
  786.      Measurements have been  taken  on  a  VAX  750  running
  787.  
  788.  
  789.  
  790.                        April 18, 1990
  791.  
  792.  
  793.  
  794.  
  795.  
  796.                            - 13 -
  797.  
  798.  
  799. 4.2BSD  under generally light load, using a batch of 297,054
  800. bytes of net.unix-wizards containing 171 articles  and  ~104
  801. cross-postings.  All times are in seconds per article.
  802.  
  803.  
  804.      time       real  user   sys               comments
  805. _____________________________________________________________________
  806. 85 Dec  6 00:54 4.68  0.3   1.29
  807.                                   BBBB nnnneeeewwwwssss rejecting all.  (b.1.rej)
  808. 85 Dec  6 00:54 3.184 0.69  0.67
  809.                                   first timing  trial;  _p_r_o_f_i_l_i_n_g  _o_n
  810.                                   (c.1)
  811. 85 Dec  6 00:54 0.66  0.175 0.199
  812.                                   rejecting all (c.2.rej)
  813. 85 Dec  6 03:25 0.58  0.175 0.175
  814.                                   still rejecting all (c.3.rej)
  815. 85 Dec  6 23:46 9.058 0.631 2.251
  816.                                   BBBB nnnneeeewwwwssss using  private  directories,
  817.                                   rejected  53 of the 171 articles as
  818.                                   "too old" (b.2)
  819. 85 Dec  7 00:24         -     -
  820.                 2.0
  821.                 (est)
  822.                                   on a 10 MHz 68000 with slow  memory
  823.                                   and   slow   disk  (crude  timings)
  824.                                   (c.darwin.1)
  825. 85 Dec  7 00:40 7.576 0.684 2.403
  826.                                   BBBB nnnneeeewwwwssss without the "too old" reject
  827.                                   code and having cleared out history
  828.                                   (b.3)
  829. 85 Dec  7 04:43 1.99  0.49  0.53
  830.                                   accepting the articles, using  read
  831.                                   and write for bulk copies (c.4)
  832. 85 Dec  7 06:10       0.497 0.449
  833.                 2.261
  834.                 (!)
  835.                                   optimized by less locking & keeping
  836.                                   batch files open (c.5)
  837. 85 Dec  7 07:32 1.383 0.491 0.414
  838.                                   same as the last one,  but  with  a
  839.                                   lower  load  average  (around  1.5)
  840.                                   (c.6)
  841. 85 Dec 16 03:43 1.380 0.447 0.374
  842.                                   for calibration after misc. cleanup
  843.                                   (c.7, c.8)
  844. 86 Jan 13 00:23 1.232 0.349 0.301
  845.                                   turned  hostchar()  into  a   macro
  846.                                   (c.9)
  847. 86 Jan 13 04:26 1.36  0.333
  848.                             0.242
  849.                             (!)
  850.                                   using in-core  active  file,  under
  851.                                   heavy load (c.10)
  852. 86 Jan 13 08:24 1.94  0.349 0.253
  853.                                   using in-core sys file  too,  under
  854.                                   heavy  load.   Re-run  this  trial!
  855.                                   (c.11)
  856. 86 Jan 13 08:42       0.332 0.245
  857.                 0.892
  858.                 (!)
  859.                                   re-run at better nice.  Not  strik-
  860.                                   ing, except for real time.  Was run
  861.                                   in  a  large   directory;   ignore.
  862.                                   (c.12)
  863. 86 Jan 13 08:59       0.333
  864.                 0.861
  865.                 (!)
  866.                             0.212
  867.                             (!)
  868.                                   re-run at good nice &  in  a  small
  869.                                   directory.   Have  beaten B news by
  870.                                   _o_n_e _o_r_d_e_r _o_f _m_a_g_n_i_t_u_d_e  on  real  &
  871.                                   sys  times!   Beat  it by more than
  872.                                   twice on user time.  (c.13)
  873. 86 Jan 21 19:15 1.208 0.349 0.245
  874.                                   creat 1st link  under  final  name,
  875.                                   only  link  to make cross-postings;
  876.                                   with HDRMEMSIZ too small (c.14)
  877. 86 Jan 21 19:57 0.728 0.318 0.193
  878.                                   previous  mod,  with  HDRMEMSIZ  of
  879.                                   4096 (c.15)
  880.  
  881.  
  882.  
  883.  
  884.  
  885.  
  886.                        April 18, 1990
  887.  
  888.  
  889.  
  890.  
  891.  
  892.                            - 14 -
  893.  
  894.  
  895. 86 Jan 22 01:20 0.719 0.315 0.166
  896.                                   fewer opens (just rewind the  spool
  897.                                   file),  but  Xref(s):  not  working
  898.                                   (c.16)
  899. 86 Jan 22 01:53       0.314
  900.                 0.637
  901.                 (!)
  902.                             0.154
  903.                             (!)
  904.                                   fewer opens fixed  to  spell  Xref:
  905.                                   right; Xref: not working (c.17)
  906. 86 Jan 22 04:00 0.874 0.325 0.174
  907.                                   fewer opens with Xref: fixed (times
  908.                                   may be high due to calendar) (c.18)
  909. 86 Jan 22 05:45 0.694 0.309 0.159
  910.                                   under  lighter  load,   times   are
  911.                                   better (c.19)
  912. 86 Jan 24 04:29 0.715 0.317
  913.                             0.129
  914.                             (!)
  915.                                   turn creat & open into just  creat,
  916.                                   under slightly heavy load (c.20)
  917. 86 Jan 24 06:06
  918.                 0.628
  919.                 (!)
  920.                       0.288
  921.                       (!)
  922.                             0.129
  923.                             (!)
  924.                                   reduce number of calls on index (by
  925.                                   noting  line  starts  at the start)
  926.                                   and   strncmp   (via   macro)    in
  927.                                   active.mem.c,  but  still profiling
  928.                                   and writing stdout  and  stderr  to
  929.                                   the tty (c.21)
  930. 86 Jan 24 07:22 0.653
  931.                       0.209
  932.                       (!)
  933.                             0.123
  934.                             (!)
  935.                                   fewer strlen calls (by using ssssiiiizzzzeeeeooooffff
  936.                                   s - 1), writing stdout to /dev/null
  937.                                   and with _p_r_o_f_i_l_i_n_g _o_f_f,  but  under
  938.                                   moderate load; try again (c.23)
  939. 86 Jan 24 07:35
  940.                 0.574
  941.                 (!)
  942.                       0.216
  943.                       (!)
  944.                             0.123
  945.                             (!)
  946.                                   as last time, but stdout to  tty(!)
  947.                                   and   under  light  load.   _r_u_n_n_i_n_g
  948.                                   _1_5._6_7 _t_i_m_e_s  _a_s  _f_a_s_t  _a_s  _B  _r_n_e_w_s
  949.                                   (c.24)
  950. 86 Aug  8 04:23 0.839 0.51  0.124
  951.                                   performance hit: fflush after  each
  952.                                   history  line for crash-resilience;
  953.                                   run for _g_p_r_o_f output  and  calibra-
  954.                                   tion   with  later  runs.   running
  955.                                   under  4.2.1BSD  (has   4.3   namei
  956.                                   cache)  now.   real  and user times
  957.                                   are way up; due to gprof profiling?
  958.                                   (c.25)
  959. 86 Aug  8 04:24 0.962       0.131
  960.                       0.438
  961.                       (!)
  962.                                   run  with  faster   ngmatch,   with
  963.                                   rrrreeeeggggiiiisssstttteeeerrrr  decl.s  and wordmatch and
  964.                                   STREQN  macros;  saved  15%   user.
  965.                                   User  time is better than c.25, but
  966.                                   still up from c.24.  (c.26)
  967. 86 Aug 10 07:35 0.805       0.135
  968.                       0.345
  969.                       (!)
  970.                                   further speedups: ngmatch has  more
  971.                                   rrrreeeeggggiiiisssstttteeeerrrr  decl.s and in-line index;
  972.                                   more  use  of  STREQ(N)  macro  for
  973.                                   str(n)cmp  in  hdrmatch,  ngmatch.c
  974.                                   and   transmit.c;   faster    ishdr
  975.                                   without  index.   real & user times
  976.                                   are better than both c.26 and  c.25
  977.                                   (c.27)
  978. 86 Aug 11 04:19 1.012       0.146
  979.                       0.303
  980.                       (!)
  981.                                   rewrote  sys.c,  used   INDEX   and
  982.                                   STREQ(N)  macros  throughout rnews.
  983.                                   real and sys times are up, but user
  984.                                   continues to decline.  (c.28)
  985. 86 Aug 12 03:51 1.315 0.315 0.154
  986.                                   minor tweaks: all.all.ctl  caching,
  987.                                   etc. (c.29)
  988.  
  989.  
  990.  
  991.  
  992.  
  993.                        April 18, 1990
  994.  
  995.  
  996.  
  997.  
  998.  
  999.                            - 15 -
  1000.  
  1001.  
  1002. 86 Aug 30 17:56 0.564
  1003.                       0.189
  1004.                       (!)
  1005.                             0.112
  1006.                             (!)
  1007.                                   light load, thought  we  had  3-arg
  1008.                                   open  in  fileart, but didn't. Odd.
  1009.                                   _S_t_o_p_p_e_d _u_s_i_n_g _g_p_r_o_f.  (c.30)
  1010. 86 Aug 30 17:57       0.191
  1011.                 0.475
  1012.                 (!)
  1013.                             0.095
  1014.                             (!)
  1015.                                   Really  and  truly  use  the  3-arg
  1016.                                   open.   _1_9  _t_i_m_e_s  _B  _r_n_e_w_s  _s_p_e_e_d.
  1017.                                   (c.31)
  1018.  
  1019.  
  1020.  
  1021.  
  1022.  
  1023.  
  1024.  
  1025.  
  1026.  
  1027.  
  1028.  
  1029.  
  1030.  
  1031.  
  1032.  
  1033.  
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.  
  1044.  
  1045.  
  1046.  
  1047.  
  1048.  
  1049.  
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061.  
  1062.  
  1063.  
  1064.  
  1065.  
  1066.  
  1067.  
  1068.  
  1069.                        April 18, 1990
  1070.  
  1071.  
  1072.