1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "nsIServiceManager.h"
39 #include "nsIComponentRegistrar.h"
40 #include "nsIInputStream.h"
41 #include "nsIOutputStream.h"
42 #include "nsIRunnable.h"
43 #include "nsIThread.h"
44 #include "nsCOMArray.h"
45 #include "nsISimpleEnumerator.h"
47 #include "nsIFileStreams.h"
48 #include "nsIFileChannel.h"
49 #include "nsILocalFile.h"
50 #include "nsNetUtil.h"
53 ////////////////////////////////////////////////////////////////////////////////
57 #include "nsAutoLock.h"
65 void AddTime(PRIntervalTime time
);
66 PRIntervalTime
LastInterval() { return mLastInterval
; }
69 PRIntervalTime mStartTime
;
73 PRIntervalTime mLastInterval
;
76 nsTimeSampler::nsTimeSampler()
82 nsTimeSampler::Reset()
92 nsTimeSampler::StartTime()
94 mStartTime
= PR_IntervalNow();
98 nsTimeSampler::EndTime()
100 NS_ASSERTION(mStartTime
!= 0, "Forgot to call StartTime");
101 PRIntervalTime endTime
= PR_IntervalNow();
102 mLastInterval
= endTime
- mStartTime
;
103 AddTime(mLastInterval
);
108 nsTimeSampler::AddTime(PRIntervalTime time
)
110 nsAutoCMonitor
mon(this);
112 mSquares
+= (double)time
* (double)time
;
117 nsTimeSampler::PrintStats()
119 double mean
= mTotalTime
/ mCount
;
120 double variance
= fabs(mSquares
/ mCount
- mean
* mean
);
121 double stddev
= sqrt(variance
);
122 PRUint32 imean
= (PRUint32
)mean
;
123 PRUint32 istddev
= (PRUint32
)stddev
;
124 return PR_smprintf("%d +/- %d ms",
125 PR_IntervalToMilliseconds(imean
),
126 PR_IntervalToMilliseconds(istddev
));
129 ////////////////////////////////////////////////////////////////////////////////
131 nsTimeSampler gTimeSampler
;
133 typedef nsresult (*CreateFun
)(nsIRunnable
* *result
,
136 PRUint32 bufferSize
);
138 ////////////////////////////////////////////////////////////////////////////////
141 Copy(nsIInputStream
* inStr
, nsIOutputStream
* outStr
,
142 char* buf
, PRUint32 bufSize
, PRUint32
*copyCount
)
147 rv
= inStr
->Read(buf
, bufSize
, &count
);
148 if (NS_FAILED(rv
)) return rv
;
149 if (count
== 0) break;
152 rv
= outStr
->Write(buf
, count
, &writeCount
);
153 if (NS_FAILED(rv
)) return rv
;
154 NS_ASSERTION(writeCount
== count
, "didn't write all the data");
155 *copyCount
+= writeCount
;
157 rv
= outStr
->Flush();
161 ////////////////////////////////////////////////////////////////////////////////
163 class FileSpecWorker
: public nsIRunnable
{
169 PRIntervalTime startTime
= PR_IntervalNow();
170 PRIntervalTime endTime
;
171 nsCOMPtr
<nsIInputStream
> inStr
;
172 nsCOMPtr
<nsIOutputStream
> outStr
;
173 PRUint32 copyCount
= 0;
175 // Open the input stream:
176 nsCOMPtr
<nsIInputStream
> fileIn
;
177 rv
= NS_NewLocalFileInputStream(getter_AddRefs(fileIn
), mInPath
);
178 if (NS_FAILED(rv
)) return rv
;
180 rv
= NS_NewBufferedInputStream(getter_AddRefs(inStr
), fileIn
, 65535);
181 if (NS_FAILED(rv
)) return rv
;
183 // Open the output stream:
184 nsCOMPtr
<nsIOutputStream
> fileOut
;
185 rv
= NS_NewLocalFileOutputStream(getter_AddRefs(fileOut
),
187 PR_CREATE_FILE
| PR_WRONLY
| PR_TRUNCATE
,
189 if (NS_FAILED(rv
)) return rv
;
191 rv
= NS_NewBufferedOutputStream(getter_AddRefs(outStr
), fileOut
, 65535);
192 if (NS_FAILED(rv
)) return rv
;
194 // Copy from one to the other
195 rv
= Copy(inStr
, outStr
, mBuffer
, mBufferSize
, ©Count
);
196 if (NS_FAILED(rv
)) return rv
;
198 endTime
= PR_IntervalNow();
199 gTimeSampler
.AddTime(endTime
- startTime
);
207 : mInPath(nsnull
), mOutPath(nsnull
), mBuffer(nsnull
),
212 nsresult
Init(nsIFile
* inPath
, nsIFile
* outPath
,
217 mBuffer
= new char[bufferSize
];
218 mBufferSize
= bufferSize
;
219 return (mInPath
&& mOutPath
&& mBuffer
)
220 ? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
223 static nsresult
Create(nsIRunnable
* *result
,
228 FileSpecWorker
* worker
= new FileSpecWorker();
229 if (worker
== nsnull
)
230 return NS_ERROR_OUT_OF_MEMORY
;
233 nsresult rv
= worker
->Init(inPath
, outPath
, bufferSize
);
242 virtual ~FileSpecWorker() {
247 nsCOMPtr
<nsIFile
> mInPath
;
248 nsCOMPtr
<nsIFile
> mOutPath
;
250 PRUint32 mBufferSize
;
253 NS_IMPL_ISUPPORTS1(FileSpecWorker
, nsIRunnable
)
255 ////////////////////////////////////////////////////////////////////////////////
257 #include "nsIIOService.h"
258 #include "nsIChannel.h"
260 class FileChannelWorker
: public nsIRunnable
{
266 PRIntervalTime startTime
= PR_IntervalNow();
267 PRIntervalTime endTime
;
268 PRUint32 copyCount
= 0;
269 nsCOMPtr
<nsIFileChannel
> inCh
;
270 nsCOMPtr
<nsIFileChannel
> outCh
;
271 nsCOMPtr
<nsIInputStream
> inStr
;
272 nsCOMPtr
<nsIOutputStream
> outStr
;
274 rv
= NS_NewLocalFileChannel(getter_AddRefs(inCh
), mInPath
);
275 if (NS_FAILED(rv
)) return rv
;
277 rv
= inCh
->Open(getter_AddRefs(inStr
));
278 if (NS_FAILED(rv
)) return rv
;
280 //rv = NS_NewLocalFileChannel(getter_AddRefs(outCh), mOutPath);
281 //if (NS_FAILED(rv)) return rv;
283 //rv = outCh->OpenOutputStream(0, -1, 0, getter_AddRefs(outStr));
284 //if (NS_FAILED(rv)) return rv;
286 // Copy from one to the other
287 rv
= Copy(inStr
, outStr
, mBuffer
, mBufferSize
, ©Count
);
288 if (NS_FAILED(rv
)) return rv
;
290 endTime
= PR_IntervalNow();
291 gTimeSampler
.AddTime(endTime
- startTime
);
299 : mInPath(nsnull
), mOutPath(nsnull
), mBuffer(nsnull
),
304 nsresult
Init(nsIFile
* inPath
, nsIFile
* outPath
,
309 mBuffer
= new char[bufferSize
];
310 mBufferSize
= bufferSize
;
311 return (mInPath
&& mOutPath
&& mBuffer
)
312 ? NS_OK
: NS_ERROR_OUT_OF_MEMORY
;
315 static nsresult
Create(nsIRunnable
* *result
,
320 FileChannelWorker
* worker
= new FileChannelWorker();
321 if (worker
== nsnull
)
322 return NS_ERROR_OUT_OF_MEMORY
;
325 nsresult rv
= worker
->Init(inPath
, outPath
, bufferSize
);
334 virtual ~FileChannelWorker() {
339 nsCOMPtr
<nsIFile
> mInPath
;
340 nsCOMPtr
<nsIFile
> mOutPath
;
342 PRUint32 mBufferSize
;
345 NS_IMPL_ISUPPORTS1(FileChannelWorker
, nsIRunnable
)
347 ////////////////////////////////////////////////////////////////////////////////
350 Test(CreateFun create
, PRUint32 count
,
351 nsIFile
* inDirSpec
, nsIFile
* outDirSpec
, PRUint32 bufSize
)
357 nsCAutoString outDir
;
358 (void)inDirSpec
->GetNativePath(inDir
);
359 (void)outDirSpec
->GetNativePath(outDir
);
360 printf("###########\nTest: from %s to %s, bufSize = %d\n",
361 inDir
.get(), outDir
.get(), bufSize
);
362 gTimeSampler
.Reset();
363 nsTimeSampler testTime
;
364 testTime
.StartTime();
366 nsCOMArray
<nsIThread
> threads
;
368 nsCOMPtr
<nsISimpleEnumerator
> entries
;
369 rv
= inDirSpec
->GetDirectoryEntries(getter_AddRefs(entries
));
370 NS_ASSERTION(NS_SUCCEEDED(rv
), "GetDirectoryEntries failed");
374 while (i
< count
&& NS_SUCCEEDED(entries
->HasMoreElements(&hasMore
)) && hasMore
) {
375 nsCOMPtr
<nsISupports
> next
;
376 rv
= entries
->GetNext(getter_AddRefs(next
));
377 if (NS_FAILED(rv
)) goto done
;
379 nsCOMPtr
<nsIFile
> inSpec
= do_QueryInterface(next
, &rv
);
380 if (NS_FAILED(rv
)) goto done
;
382 nsCOMPtr
<nsIFile
> outSpec
;
383 rv
= outDirSpec
->Clone(getter_AddRefs(outSpec
)); // don't munge the original
384 if (NS_FAILED(rv
)) goto done
;
386 nsCAutoString leafName
;
387 rv
= inSpec
->GetNativeLeafName(leafName
);
388 if (NS_FAILED(rv
)) goto done
;
390 rv
= outSpec
->AppendNative(leafName
);
391 if (NS_FAILED(rv
)) goto done
;
394 rv
= outSpec
->Exists(&exists
);
395 if (NS_FAILED(rv
)) goto done
;
398 rv
= outSpec
->Remove(PR_FALSE
);
399 if (NS_FAILED(rv
)) goto done
;
402 nsCOMPtr
<nsIThread
> thread
;
403 nsCOMPtr
<nsIRunnable
> worker
;
404 rv
= create(getter_AddRefs(worker
),
408 if (NS_FAILED(rv
)) goto done
;
410 rv
= NS_NewThread(getter_AddRefs(thread
), worker
, 0, PR_JOINABLE_THREAD
);
411 if (NS_FAILED(rv
)) goto done
;
413 PRBool inserted
= threads
.InsertObjectAt(thread
, i
);
414 NS_ASSERTION(inserted
, "not inserted");
420 for (j
= 0; j
< i
; j
++) {
421 nsIThread
* thread
= threads
.ObjectAt(j
);
426 NS_ASSERTION(rv
== NS_OK
, "failed");
429 char* testStats
= testTime
.PrintStats();
430 char* workerStats
= gTimeSampler
.PrintStats();
431 printf(" threads = %d\n work time = %s,\n test time = %s\n",
432 i
, workerStats
, testStats
);
433 PR_smprintf_free(workerStats
);
434 PR_smprintf_free(testStats
);
437 ////////////////////////////////////////////////////////////////////////////////
440 main(int argc
, char* argv
[])
445 printf("usage: %s <in-dir> <out-dir>\n", argv
[0]);
448 char* inDir
= argv
[1];
449 char* outDir
= argv
[2];
452 nsCOMPtr
<nsIServiceManager
> servMan
;
453 NS_InitXPCOM2(getter_AddRefs(servMan
), nsnull
, nsnull
);
454 nsCOMPtr
<nsIComponentRegistrar
> registrar
= do_QueryInterface(servMan
);
455 NS_ASSERTION(registrar
, "Null nsIComponentRegistrar");
457 registrar
->AutoRegister(nsnull
);
459 nsCOMPtr
<nsILocalFile
> inDirFile
;
460 rv
= NS_NewNativeLocalFile(nsDependentCString(inDir
), PR_FALSE
, getter_AddRefs(inDirFile
));
461 if (NS_FAILED(rv
)) return rv
;
463 nsCOMPtr
<nsILocalFile
> outDirFile
;
464 rv
= NS_NewNativeLocalFile(nsDependentCString(outDir
), PR_FALSE
, getter_AddRefs(outDirFile
));
465 if (NS_FAILED(rv
)) return rv
;
467 CreateFun create
= FileChannelWorker::Create
;
468 Test(create
, 1, inDirFile
, outDirFile
, 16 * 1024);
470 printf("FileChannelWorker *****************************\n");
471 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
472 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
473 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
474 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
475 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
476 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
477 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
478 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
479 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
481 create
= FileSpecWorker::Create
;
482 printf("FileSpecWorker ********************************\n");
484 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
485 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
486 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
487 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
488 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
489 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
490 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
491 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
492 Test(create
, 20, inDirFile
, outDirFile
, 16 * 1024);
495 Test(create
, 20, inDirFile
, outDirFile
, 4 * 1024);
496 Test(create
, 20, inDirFile
, outDirFile
, 4 * 1024);
497 Test(create
, 20, inDirFile
, outDirFile
, 4 * 1024);
498 Test(create
, 20, inDirFile
, outDirFile
, 4 * 1024);
499 Test(create
, 20, inDirFile
, outDirFile
, 4 * 1024);
500 Test(create
, 20, inDirFile
, outDirFile
, 4 * 1024);
501 Test(create
, 20, inDirFile
, outDirFile
, 4 * 1024);
502 Test(create
, 20, inDirFile
, outDirFile
, 4 * 1024);
503 Test(create
, 20, inDirFile
, outDirFile
, 4 * 1024);
505 } // this scopes the nsCOMPtrs
506 // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM
507 rv
= NS_ShutdownXPCOM(nsnull
);
508 NS_ASSERTION(NS_SUCCEEDED(rv
), "NS_ShutdownXPCOM failed");
512 ////////////////////////////////////////////////////////////////////////////////