<br><br><div class="gmail_quote">On Tue, Feb 9, 2010 at 3:44 PM, David T. Lewis <span dir="ltr">&lt;<a href="mailto:lewis@mail.msen.com">lewis@mail.msen.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
A bit of a strain on the old garbage collector, but a Bag is good<br>
for that kind of analysis:<br>
<br>
  f := FileStream fileNamed: &#39;strace.txt&#39;.<br>
  lines := Bag new.<br>
  [[f atEnd] whileFalse: [lines add: (f upTo: Character lf)]]<br>
      ensure: [f close].<br>
  lines sortedCounts inspect<br></blockquote><div><br></div><div>That doesn&#39;t do what I want.  That gives the frequency of each line.  I want a shortened file that I can browse more easily where successive runs of multiple lines are compressed down to a single run of the multiple lines marked with a repeat count.  Instead of having to wade through pages and pages of the same N lines there is just one occurrence of those N lines prefixed with a repeat count.  So the condensed log preserves the ordering of the events it logs but is much abbreviated.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
Dave<br>
<div><div></div><div class="h5"><br>
On Tue, Feb 09, 2010 at 01:34:19PM -0800, Eliot Miranda wrote:<br>
&gt; Hi All,<br>
&gt;<br>
&gt;     I&#39;ve just needed to make sense of a very long log file generated by<br>
&gt; strace.  The log file is full of entries like:<br>
&gt;<br>
&gt; --- SIGALRM (Alarm clock) @ 0 (0) ---<br>
&gt; gettimeofday({1265744804, 491238}, NULL) = 0<br>
&gt; sigreturn()                             = ? (mask now [])<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt;<br>
&gt; and my workspace script reduces these to e.g.<br>
&gt;<br>
&gt; --- SIGALRM (Alarm clock) @ 0 (0) ---<br>
&gt; gettimeofday({1265744797, 316183}, NULL) = 0<br>
&gt; sigreturn()                             = ? (mask now [])<br>
&gt; NEXT 2 LINES REPEAT 715 TIMES<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; --- SIGALRM (Alarm clock) @ 0 (0) ---<br>
&gt; gettimeofday({1265744797, 317189}, NULL) = 0<br>
&gt; sigreturn()                             = ? (mask now [])<br>
&gt;<br>
&gt;<br>
&gt; My question is has anyone looked at this issue in any depth and perhaps come<br>
&gt; up with something not as crude as the below and possibly even recursive.<br>
&gt;  i.e. the above would ideally be reduced to e.g.<br>
&gt;<br>
&gt; NEXT 7 LINES REPEAT 123456 TIMES<br>
&gt; --- SIGALRM (Alarm clock) @ 0 (0) ---<br>
&gt; gettimeofday({1265744797, 316183}, NULL) = 0<br>
&gt; sigreturn()                             = ? (mask now [])<br>
&gt; NEXT 2 LINES REPEAT BETWEEN 500 AND 800 TIMES<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; ioctl(8, 0x80045530, 0xbfd4fe70)        = 0<br>
&gt; ioctl(8, 0xc1205531, 0xbfd4fb80)        = 0<br>
&gt; --- SIGALRM (Alarm clock) @ 0 (0) ---<br>
&gt; gettimeofday({1265744797, 317189}, NULL) = 0<br>
&gt; sigreturn()                             = ? (mask now [])<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; Here&#39;s my quick hack that I ran in vw7.7nc:<br>
&gt;<br>
&gt; | f o lines maxrun repeats range |<br>
&gt; f := &#39;../Cog/squeak.strace.log&#39; asFilename readStream.<br>
&gt; o := &#39;compressed.log&#39; asFilename writeStream.<br>
&gt; lines := OrderedCollection new.<br>
&gt; maxrun := 50.<br>
&gt; repeats := 0.<br>
&gt; range := nil.<br>
&gt; [[f atEnd] whileFalse:<br>
&gt; [lines size &gt; maxrun ifTrue:<br>
&gt; [repeats &gt; 0<br>
&gt; ifTrue:<br>
&gt; [1 to: range first - 1 do:<br>
&gt; [:i| o nextPutAll: (lines at: i); cr].<br>
&gt; o nextPutAll: &#39;NEXT &#39;; print: range size; nextPutAll: &#39; LINES REPEAT &#39;;<br>
&gt; print: repeats + 1; nextPutAll: &#39; TIMES&#39;; cr.<br>
&gt; range do:<br>
&gt; [:i| o nextPutAll: (lines at: i); cr].<br>
&gt; lines removeFirst: range last.<br>
&gt; repeats := 0]<br>
&gt; ifFalse:<br>
&gt; [o nextPutAll: lines removeFirst; cr; flush].<br>
&gt;  range := nil].<br>
&gt; lines addLast: (f upTo: Character cr).<br>
&gt; [:exit|<br>
&gt; 1 to: lines size do:<br>
&gt; [:i| | line repeat |<br>
&gt; line := lines at: i.<br>
&gt; repeat := lines nextIndexOf: line from: i + 1 to: lines size.<br>
&gt; (repeat ~~ nil<br>
&gt;  and: [lines size &gt;= (repeat - i * 2 + i)<br>
&gt;  and: [(i to: repeat - 1) allSatisfy: [:j| (lines at: j) = (lines at: j - i<br>
&gt; + repeat)]]]) ifTrue:<br>
&gt; [repeats := repeats + 1.<br>
&gt;  range isNil<br>
&gt; ifTrue: [range := i to: repeat - 1]<br>
&gt; ifFalse:<br>
&gt; [range = (i to: repeat - 1) ifTrue:<br>
&gt; [range do: [:ignore| lines removeAtIndex: repeat].<br>
&gt;  exit value]]]]] valueWithExit]]<br>
&gt; ensure: [f close. o close].<br>
&gt; repeats<br>
&gt;<br>
&gt; Forgive the cross post.  I expect deep expertise in each newsgroup posted<br>
&gt; to.<br>
&gt;<br>
&gt; best<br>
&gt; Eliot<br>
<br>
&gt;<br>
<br>
<br>
</div></div></blockquote></div><br>