diff options
Diffstat (limited to 'netwerk/test/TestFileInput2.cpp')
-rw-r--r-- | netwerk/test/TestFileInput2.cpp | 480 |
1 files changed, 480 insertions, 0 deletions
diff --git a/netwerk/test/TestFileInput2.cpp b/netwerk/test/TestFileInput2.cpp new file mode 100644 index 000000000..f51988010 --- /dev/null +++ b/netwerk/test/TestFileInput2.cpp @@ -0,0 +1,480 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsIServiceManager.h" +#include "nsIComponentRegistrar.h" +#include "nsIInputStream.h" +#include "nsIOutputStream.h" +#include "nsIRunnable.h" +#include "nsIThread.h" +#include "nsCOMArray.h" +#include "nsISimpleEnumerator.h" +#include "prinrval.h" +#include "nsIFileStreams.h" +#include "nsIFileChannel.h" +#include "nsIFile.h" +#include "nsNetUtil.h" +#include <stdio.h> + +//////////////////////////////////////////////////////////////////////////////// + +#include <math.h> +#include "prprf.h" +#include "nsAutoLock.h" + +class nsTimeSampler { +public: + nsTimeSampler(); + void Reset(); + void StartTime(); + void EndTime(); + void AddTime(PRIntervalTime time); + PRIntervalTime LastInterval() { return mLastInterval; } + char* PrintStats(); +protected: + PRIntervalTime mStartTime; + double mSquares; + double mTotalTime; + uint32_t mCount; + PRIntervalTime mLastInterval; +}; + +nsTimeSampler::nsTimeSampler() +{ + Reset(); +} + +void +nsTimeSampler::Reset() +{ + mStartTime = 0; + mSquares = 0; + mTotalTime = 0; + mCount = 0; + mLastInterval = 0; +} + +void +nsTimeSampler::StartTime() +{ + mStartTime = PR_IntervalNow(); +} + +void +nsTimeSampler::EndTime() +{ + NS_ASSERTION(mStartTime != 0, "Forgot to call StartTime"); + PRIntervalTime endTime = PR_IntervalNow(); + mLastInterval = endTime - mStartTime; + AddTime(mLastInterval); + mStartTime = 0; +} + +void +nsTimeSampler::AddTime(PRIntervalTime time) +{ + nsAutoCMonitor mon(this); + mTotalTime += time; + mSquares += (double)time * (double)time; + mCount++; +} + +char* +nsTimeSampler::PrintStats() +{ + double mean = mTotalTime / mCount; + double variance = fabs(mSquares / mCount - mean * mean); + double stddev = sqrt(variance); + uint32_t imean = (uint32_t)mean; + uint32_t istddev = (uint32_t)stddev; + return PR_smprintf("%d +/- %d ms", + PR_IntervalToMilliseconds(imean), + PR_IntervalToMilliseconds(istddev)); +} + +//////////////////////////////////////////////////////////////////////////////// + +nsTimeSampler gTimeSampler; + +typedef nsresult (*CreateFun)(nsIRunnable* *result, + nsIFile* inPath, + nsIFile* outPath, + uint32_t bufferSize); + +//////////////////////////////////////////////////////////////////////////////// + +nsresult +Copy(nsIInputStream* inStr, nsIOutputStream* outStr, + char* buf, uint32_t bufSize, uint32_t *copyCount) +{ + nsresult rv; + while (true) { + uint32_t count; + rv = inStr->Read(buf, bufSize, &count); + if (NS_FAILED(rv)) return rv; + if (count == 0) break; + + uint32_t writeCount; + rv = outStr->Write(buf, count, &writeCount); + if (NS_FAILED(rv)) return rv; + NS_ASSERTION(writeCount == count, "didn't write all the data"); + *copyCount += writeCount; + } + rv = outStr->Flush(); + return rv; +} + +//////////////////////////////////////////////////////////////////////////////// + +class FileSpecWorker : public nsIRunnable { +public: + + NS_IMETHOD Run() override { + nsresult rv; + + PRIntervalTime startTime = PR_IntervalNow(); + PRIntervalTime endTime; + nsCOMPtr<nsIInputStream> inStr; + nsCOMPtr<nsIOutputStream> outStr; + uint32_t copyCount = 0; + + // Open the input stream: + nsCOMPtr<nsIInputStream> fileIn; + rv = NS_NewLocalFileInputStream(getter_AddRefs(fileIn), mInPath); + if (NS_FAILED(rv)) return rv; + + rv = NS_NewBufferedInputStream(getter_AddRefs(inStr), fileIn, 65535); + if (NS_FAILED(rv)) return rv; + + // Open the output stream: + nsCOMPtr<nsIOutputStream> fileOut; + rv = NS_NewLocalFileOutputStream(getter_AddRefs(fileOut), + mOutPath, + PR_CREATE_FILE | PR_WRONLY | PR_TRUNCATE, + 0664); + if (NS_FAILED(rv)) return rv; + + rv = NS_NewBufferedOutputStream(getter_AddRefs(outStr), fileOut, 65535); + if (NS_FAILED(rv)) return rv; + + // Copy from one to the other + rv = Copy(inStr, outStr, mBuffer, mBufferSize, ©Count); + if (NS_FAILED(rv)) return rv; + + endTime = PR_IntervalNow(); + gTimeSampler.AddTime(endTime - startTime); + + return rv; + } + + NS_DECL_ISUPPORTS + + FileSpecWorker() + : mInPath(nullptr), mOutPath(nullptr), mBuffer(nullptr), + mBufferSize(0) + { + } + + nsresult Init(nsIFile* inPath, nsIFile* outPath, + uint32_t bufferSize) + { + mInPath = inPath; + mOutPath = outPath; + mBuffer = new char[bufferSize]; + mBufferSize = bufferSize; + return (mInPath && mOutPath && mBuffer) + ? NS_OK : NS_ERROR_OUT_OF_MEMORY; + } + + static nsresult Create(nsIRunnable* *result, + nsIFile* inPath, + nsIFile* outPath, + uint32_t bufferSize) + { + FileSpecWorker* worker = new FileSpecWorker(); + if (worker == nullptr) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(worker); + + nsresult rv = worker->Init(inPath, outPath, bufferSize); + if (NS_FAILED(rv)) { + NS_RELEASE(worker); + return rv; + } + *result = worker; + return NS_OK; + } + + virtual ~FileSpecWorker() { + delete[] mBuffer; + } + +protected: + nsCOMPtr<nsIFile> mInPath; + nsCOMPtr<nsIFile> mOutPath; + char* mBuffer; + uint32_t mBufferSize; +}; + +NS_IMPL_ISUPPORTS(FileSpecWorker, nsIRunnable) + +//////////////////////////////////////////////////////////////////////////////// + +#include "nsIIOService.h" +#include "nsIChannel.h" + +class FileChannelWorker : public nsIRunnable { +public: + + NS_IMETHOD Run() override { + nsresult rv; + + PRIntervalTime startTime = PR_IntervalNow(); + PRIntervalTime endTime; + uint32_t copyCount = 0; + nsCOMPtr<nsIFileChannel> inCh; + nsCOMPtr<nsIFileChannel> outCh; + nsCOMPtr<nsIInputStream> inStr; + nsCOMPtr<nsIOutputStream> outStr; + + rv = NS_NewLocalFileChannel(getter_AddRefs(inCh), mInPath); + if (NS_FAILED(rv)) return rv; + + rv = inCh->Open(getter_AddRefs(inStr)); + if (NS_FAILED(rv)) return rv; + + //rv = NS_NewLocalFileChannel(getter_AddRefs(outCh), mOutPath); + //if (NS_FAILED(rv)) return rv; + + //rv = outCh->OpenOutputStream(0, -1, 0, getter_AddRefs(outStr)); + //if (NS_FAILED(rv)) return rv; + + // Copy from one to the other + rv = Copy(inStr, outStr, mBuffer, mBufferSize, ©Count); + if (NS_FAILED(rv)) return rv; + + endTime = PR_IntervalNow(); + gTimeSampler.AddTime(endTime - startTime); + + return rv; + } + + NS_DECL_ISUPPORTS + + FileChannelWorker() + : mInPath(nullptr), mOutPath(nullptr), mBuffer(nullptr), + mBufferSize(0) + { + } + + nsresult Init(nsIFile* inPath, nsIFile* outPath, + uint32_t bufferSize) + { + mInPath = inPath; + mOutPath = outPath; + mBuffer = new char[bufferSize]; + mBufferSize = bufferSize; + return (mInPath && mOutPath && mBuffer) + ? NS_OK : NS_ERROR_OUT_OF_MEMORY; + } + + static nsresult Create(nsIRunnable* *result, + nsIFile* inPath, + nsIFile* outPath, + uint32_t bufferSize) + { + FileChannelWorker* worker = new FileChannelWorker(); + if (worker == nullptr) + return NS_ERROR_OUT_OF_MEMORY; + NS_ADDREF(worker); + + nsresult rv = worker->Init(inPath, outPath, bufferSize); + if (NS_FAILED(rv)) { + NS_RELEASE(worker); + return rv; + } + *result = worker; + return NS_OK; + } + + virtual ~FileChannelWorker() { + delete[] mBuffer; + } + +protected: + nsCOMPtr<nsIFile> mInPath; + nsCOMPtr<nsIFile> mOutPath; + char* mBuffer; + uint32_t mBufferSize; +}; + +NS_IMPL_ISUPPORTS(FileChannelWorker, nsIRunnable) + +//////////////////////////////////////////////////////////////////////////////// + +void +Test(CreateFun create, uint32_t count, + nsIFile* inDirSpec, nsIFile* outDirSpec, uint32_t bufSize) +{ + nsresult rv; + uint32_t i; + + nsAutoCString inDir; + nsAutoCString outDir; + (void)inDirSpec->GetNativePath(inDir); + (void)outDirSpec->GetNativePath(outDir); + printf("###########\nTest: from %s to %s, bufSize = %d\n", + inDir.get(), outDir.get(), bufSize); + gTimeSampler.Reset(); + nsTimeSampler testTime; + testTime.StartTime(); + + nsCOMArray<nsIThread> threads; + + nsCOMPtr<nsISimpleEnumerator> entries; + rv = inDirSpec->GetDirectoryEntries(getter_AddRefs(entries)); + NS_ASSERTION(NS_SUCCEEDED(rv), "GetDirectoryEntries failed"); + + i = 0; + bool hasMore; + while (i < count && NS_SUCCEEDED(entries->HasMoreElements(&hasMore)) && hasMore) { + nsCOMPtr<nsISupports> next; + rv = entries->GetNext(getter_AddRefs(next)); + if (NS_FAILED(rv)) goto done; + + nsCOMPtr<nsIFile> inSpec = do_QueryInterface(next, &rv); + if (NS_FAILED(rv)) goto done; + + nsCOMPtr<nsIFile> outSpec; + rv = outDirSpec->Clone(getter_AddRefs(outSpec)); // don't munge the original + if (NS_FAILED(rv)) goto done; + + nsAutoCString leafName; + rv = inSpec->GetNativeLeafName(leafName); + if (NS_FAILED(rv)) goto done; + + rv = outSpec->AppendNative(leafName); + if (NS_FAILED(rv)) goto done; + + bool exists; + rv = outSpec->Exists(&exists); + if (NS_FAILED(rv)) goto done; + + if (exists) { + rv = outSpec->Remove(false); + if (NS_FAILED(rv)) goto done; + } + + nsCOMPtr<nsIThread> thread; + nsCOMPtr<nsIRunnable> worker; + rv = create(getter_AddRefs(worker), + inSpec, + outSpec, + bufSize); + if (NS_FAILED(rv)) goto done; + + rv = NS_NewThread(getter_AddRefs(thread), worker, 0, PR_JOINABLE_THREAD); + if (NS_FAILED(rv)) goto done; + + bool inserted = threads.InsertObjectAt(thread, i); + NS_ASSERTION(inserted, "not inserted"); + + i++; + } + + uint32_t j; + for (j = 0; j < i; j++) { + nsIThread* thread = threads.ObjectAt(j); + thread->Join(); + } + + done: + NS_ASSERTION(rv == NS_OK, "failed"); + + testTime.EndTime(); + char* testStats = testTime.PrintStats(); + char* workerStats = gTimeSampler.PrintStats(); + printf(" threads = %d\n work time = %s,\n test time = %s\n", + i, workerStats, testStats); + PR_smprintf_free(workerStats); + PR_smprintf_free(testStats); +} + +//////////////////////////////////////////////////////////////////////////////// + +int +main(int argc, char* argv[]) +{ + nsresult rv; + + if (argc < 2) { + printf("usage: %s <in-dir> <out-dir>\n", argv[0]); + return -1; + } + char* inDir = argv[1]; + char* outDir = argv[2]; + + { + nsCOMPtr<nsIServiceManager> servMan; + NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); + nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan); + NS_ASSERTION(registrar, "Null nsIComponentRegistrar"); + if (registrar) + registrar->AutoRegister(nullptr); + + nsCOMPtr<nsIFile> inDirFile; + rv = NS_NewNativeLocalFile(nsDependentCString(inDir), false, getter_AddRefs(inDirFile)); + if (NS_FAILED(rv)) return rv; + + nsCOMPtr<nsIFile> outDirFile; + rv = NS_NewNativeLocalFile(nsDependentCString(outDir), false, getter_AddRefs(outDirFile)); + if (NS_FAILED(rv)) return rv; + + CreateFun create = FileChannelWorker::Create; + Test(create, 1, inDirFile, outDirFile, 16 * 1024); +#if 1 + printf("FileChannelWorker *****************************\n"); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); +#endif + create = FileSpecWorker::Create; + printf("FileSpecWorker ********************************\n"); +#if 1 + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); + Test(create, 20, inDirFile, outDirFile, 16 * 1024); +#endif +#if 1 + Test(create, 20, inDirFile, outDirFile, 4 * 1024); + Test(create, 20, inDirFile, outDirFile, 4 * 1024); + Test(create, 20, inDirFile, outDirFile, 4 * 1024); + Test(create, 20, inDirFile, outDirFile, 4 * 1024); + Test(create, 20, inDirFile, outDirFile, 4 * 1024); + Test(create, 20, inDirFile, outDirFile, 4 * 1024); + Test(create, 20, inDirFile, outDirFile, 4 * 1024); + Test(create, 20, inDirFile, outDirFile, 4 * 1024); + Test(create, 20, inDirFile, outDirFile, 4 * 1024); +#endif + } // this scopes the nsCOMPtrs + // no nsCOMPtrs are allowed to be alive when you call NS_ShutdownXPCOM + rv = NS_ShutdownXPCOM(nullptr); + NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed"); + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// |