textrendering/textformatting/test/src/TFormBenchmark.cpp
changeset 0 1fb32624e06b
child 51 a7c938434754
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/textrendering/textformatting/test/src/TFormBenchmark.cpp	Tue Feb 02 02:02:46 2010 +0200
@@ -0,0 +1,722 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+
+
+#include "TCustomWrap.h"
+#include "TGraphicsContext.h"
+#include <e32std.h>
+#include <e32test.h>
+#include <frmtlay.h>
+#include <frmtview.h>
+#include <txtlaydc.h>
+#include <fbs.h>
+#include <w32std.h>
+#include <txtrich.h>
+#include <e32math.h>
+#include <f32file.h>
+#include <flogger.h>
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include "TAGMA_INTERNAL.H"
+#endif
+
+RFs fs;
+RFile fileTimeStamps;
+
+#if ((defined (__WINS__)) || (defined (__X86GCC__)))
+	_LIT(KLogTimeStampsName, "c:\\formtimestamps.csv");
+#else
+	_LIT(KLogTimeStampsName, "e:\\formtimestamps.csv");
+#endif
+
+_LIT(KEnglish, "Whereas recognition of the inherent dignity and of the equal \
+and inalienable rights of all members of the human family is the foundation \
+of freedom, justice and peace in the world, ");
+const TInt KEnglishRepeats = 119;
+_LIT(KArabic, "\x644\x645\x651\x627 \x643\x627\x646 \x627\x644\x627\x639\x62A\
+\x631\x627\x641 \x628\x627\x644\x643\x631\x627\x645\x629 \x627\x644\x645\x62A\
+\x623\x635\x644\x629 \x641\x64A \x62C\x645\x64A\x639 \x623\x639\x636\x627\
+\x621 \x627\x644\x623\x633\x631\x629 \x627\x644\x628\x634\x631\x64A\x629\
+ \x648\x628\x62D\x642\x648\x642\x647\x645 \x627\x644\x645\x62A\x633\x627\
+\x648\x64A\x629 \x627\x644\x62B\x627\x628\x62A\x629 \x647\x648 \x623\x633\
+\x627\x633 \x627\x644\x62D\x631\x64A\x629 \x648\x627\x644\x639\x62F\x644\
+ \x648\x627\x644\x633\x644\x627\x645 \x641\x64A \x627\x644\x639\x627\x644\
+\x645. ");
+const TInt KArabicRepeats = 156;
+_LIT(KJapanese, "\x4EBA\x985E\x793E\x4F1A\x306E\x3059\x3079\x3066\x306E\x69CB\
+\x6210\x54E1\x306E\x56FA\x6709\x306E\x5C0A\x53B3\x3068\x5E73\x7B49\x3067\x8B72\
+\x308B\x3053\x3068\x306E\x3067\x304D\x306A\x3044\x6A29\x5229\x3068\x3092\
+\x627F\x8A8D\x3059\x308B\x3053\x3068\x306F\x3001\x4E16\x754C\x306B\x304A\
+\x3051\x308B\x81EA\x7531\x3001\x6B63\x7FA9\x53CA\x3073\x5E73\x548C\x306E\
+\x57FA\x790E\x3067\x3042\x308B\x306E\x3067\x3001 ");
+const TInt KJapaneseRepeats = 357;
+const TInt KDisplayWidth = 100;
+const TInt KDisplayHeight = 120;
+
+
+_LIT(KFormBenchmark, "TFormBenchmark");
+RTest test(KFormBenchmark);
+
+const TInt KInsertDisplayWidth = 200;
+const TInt KChangedDisplayWidth = 150;
+
+_LIT(KEnglishToInsert1, "Whereas recognition of the inherent dignity");
+_LIT(KEnglishToInsert2, " and of the equal and inalienable rights of all... and so on");
+
+const TInt KEnglishInsertRepeats = 400;
+const TInt KEnglishScrollRepeats = 100;
+
+const TInt KDeleteTextInterval = 10;//we measure delete text once for each 10 deletes, to make the output smaller
+
+_LIT8(KDeleteTextFromStart, "Delete text from start\r\n");
+_LIT8(KInsertTextAtStart, "Insert text at start\r\n");
+_LIT8(KScrollingUp, "Scrolling up\r\n");
+_LIT8(KScrollingDown, "Scrolling down\r\n");
+
+struct TDocInfo
+	{
+	TDocInfo():iDocLength(0), iDocParaCount(0), iLineCount(0){}
+	TInt iDocLength;
+	TInt iDocParaCount;
+	TInt iLineCount;
+	};
+
+struct TTFTimeStamp
+	{
+	TInt64 iTime;
+	TInt iIteration;
+	};
+
+struct TFormattingObjects
+	{
+	TRect* iDisplayRect;
+	CParaFormatLayer* iParFormat;
+	CCharFormatLayer* iCharFormat;
+	CRichText* iRichText;
+	CTextLayout* iLayout;
+	CTestGraphicsDevice* iDevice;
+	CTextView* iView;
+	};
+
+/*
+Functions for writing benchmarking data to the CSV
+*/
+void WriteSampleDocInfo(TDocInfo aDocInfo, RFile aDest)
+	{
+	TBuf8<128> buf;
+	buf.Format(_L8("Sample text: %d characters: %d paras: %d lines\r\n"), aDocInfo.iDocLength, aDocInfo.iDocParaCount, aDocInfo.iLineCount);
+	aDest.Write(buf);
+	}
+
+void WriteTimeStampsL(const TDesC8& aTitle, RArray<TTFTimeStamp>& aTimeStamps)
+	{
+	fileTimeStamps.Write(aTitle);
+	for (TInt i = 0; i < aTimeStamps.Count(); i++)
+		{
+		TTFTimeStamp timestamp = aTimeStamps[i];
+		TBuf8<128> buf;
+		buf.Format(_L8("%d, %Ld\r\n"), timestamp.iIteration, timestamp.iTime/1000);
+		fileTimeStamps.Write(buf);
+		}
+	}
+
+TDocInfo GetSampleDocInfoL(TFormattingObjects& aFormattingObjects)
+	{
+	TDocInfo docInfo;
+	const CTmTextLayout& layout = aFormattingObjects.iView->Layout()->TagmaTextLayout();
+	docInfo.iDocLength = layout.Source()->DocumentLength();
+	docInfo.iDocParaCount = aFormattingObjects.iRichText->ParagraphCount();
+//very peculiar way to count the lines...
+	TCursorPosition::TMovementType move = TCursorPosition::EFLineDown;
+	while (move == TCursorPosition::EFLineDown)
+		{
+		aFormattingObjects.iView->MoveCursorL(move, EFalse);
+		}
+	move = TCursorPosition::EFLineUp;
+	while (move == TCursorPosition::EFLineUp)
+		{
+		docInfo.iLineCount++;
+		aFormattingObjects.iView->MoveCursorL(move, EFalse);
+		}
+	return docInfo;
+	}
+
+/*
+Set up the test document
+*/
+void SetTextL(CRichText& aText, const TDesC& aSample, TInt aRepeats, TInt aRepeatsPerPara)
+	{
+	TInt repeatsInThisPar = 0;
+	aText.Reset();
+	for (; aRepeats != 0; --aRepeats)
+		{
+		aText.InsertL(0, aSample);
+		repeatsInThisPar ++;
+		if (repeatsInThisPar > aRepeatsPerPara)
+			{
+			TChar paragraphDelimiter(0x2029);
+			aText.InsertL(0, paragraphDelimiter);
+			repeatsInThisPar = 0;
+			}
+		}
+	}
+
+_LIT(KOneWord, "blahblahblahblahblahblahblahblah");
+
+void BigBufLC(RBuf& aBigBuf)
+	{
+	aBigBuf.CreateL(16384);
+	aBigBuf.CleanupClosePushL();
+	while(aBigBuf.Length()+KOneWord().Length() < aBigBuf.MaxLength())
+		{
+		aBigBuf.Append(KOneWord);
+		}
+	}
+
+TTimeIntervalMicroSeconds MeasureOpeningL(CTextView& aView)
+	{
+	TCursorSelection zero(0, 0);
+	aView.SetPendingSelection(zero);
+	TTime start;
+	TTime end;
+	start.UniversalTime();
+	aView.HandleGlobalChangeL();
+	end.UniversalTime();
+	return end.MicroSecondsFrom(start);
+	}
+
+TTimeIntervalMicroSeconds MeasureRmsCursorDownL(CTextView& aView)
+	{
+	TInt mem;
+	TInt cells = User::AllocSize(mem);
+	TReal totalOfSquares = 0;
+	TTime start;
+	TTime end;
+	TCursorPosition::TMovementType move = TCursorPosition::EFLineDown;
+	while (move == TCursorPosition::EFLineDown)
+		{
+		start.UniversalTime();
+		aView.MoveCursorL(move, EFalse);
+		end.UniversalTime();
+		TReal us = end.MicroSecondsFrom(start).Int64();
+		totalOfSquares += us*us;
+		}
+	TReal rms;
+	Math::Sqrt(rms, totalOfSquares);
+	cells = User::AllocSize(mem);
+	return TTimeIntervalMicroSeconds(static_cast<TInt64>(rms));
+	}
+
+TInt NumberOfLines(CTextLayout& aLayout)
+	{
+	TTmDocPosSpec dp(aLayout.DocumentLength(), TTmDocPosSpec::ETrailing);
+	TTmPosInfo2 posInfo;
+	TTmLineInfo lineInfo;
+	aLayout.FindDocPos(dp, posInfo, &lineInfo);
+	return lineInfo.iLineNumber;
+	}
+
+TTimeIntervalMicroSeconds MeasureFormattingL(CTextView& aView)
+	{
+	// This looks to me like a defect.
+	// We have to set the actual doc pos to prevent a crash, even
+	// though we are setting a pending selection.
+	// Probably not too serious, though.
+	aView.SetDocPosL(0, ETrue);
+	TCursorSelection zero(0, 0);
+	aView.SetPendingSelection(zero);
+	TTime start;
+	TTime end;
+	start.UniversalTime();
+	aView.HandleGlobalChangeL();
+	aView.FinishBackgroundFormattingL();
+	end.UniversalTime();
+	end.UniversalTime();
+	return end.MicroSecondsFrom(start);
+	}
+
+void MeasureDeleteTextFromStartL(RArray<TTFTimeStamp>& aTimeStamps,
+	TFormattingObjects& aFormattingObjects, TInt64& aSlowest)
+	{
+	const CTmTextLayout& tmLayout = aFormattingObjects.iLayout->TagmaTextLayout();
+	aTimeStamps.Close();
+	TTime start;
+	TTime end;
+	TInt iteration = 0;
+	TInt64 total = 0;
+
+	TInt step = 0;
+	while(aFormattingObjects.iRichText->DocumentLength() > 0)
+		{
+		aFormattingObjects.iRichText->DeleteL(0, 1);
+		TCursorSelection cursor(0,0);
+		start.UniversalTime();
+		aFormattingObjects.iView->HandleInsertDeleteL(cursor, 1, EFalse);
+		end.UniversalTime();
+
+		TInt64 us = end.MicroSecondsFrom(start).Int64();
+
+		if(us > aSlowest)
+			{
+			aSlowest = us;
+			}
+
+		total += us;
+		step++;
+		if(step == KDeleteTextInterval)
+			{
+			TInt64 average = total/KDeleteTextInterval;
+			TTFTimeStamp timestamp;
+			timestamp.iTime = average;
+			timestamp.iIteration = iteration;
+			User::LeaveIfError(aTimeStamps.Append(timestamp));
+			iteration++;
+			step = 0;
+			total = 0;
+			}
+		}
+	}
+
+void MeasureInsertTextAtStartL(TInt aRepeats, TInt aRepeatsPerPara, RArray<TTFTimeStamp>& aTimeStamps,
+	TFormattingObjects& aFormattingObjects, TInt64& aSlowest)
+	{
+	aTimeStamps.Close();
+	TTime start;
+	TTime end;
+	TInt repeatsInThisPar = 0;
+	TViewRectChanges changes;
+	aFormattingObjects.iRichText->Reset();
+	for (TInt i = 0; i < aRepeats; i++)
+		{
+		TBuf<128> sample;
+		if ((i%2)==0)
+			{
+			sample = KEnglishToInsert1;
+			}
+		else
+			{
+			sample = KEnglishToInsert2;
+			}
+		aFormattingObjects.iRichText->InsertL(0, sample);
+		TCursorSelection cursor(0, sample.Length());
+
+		start.UniversalTime();
+		aFormattingObjects.iLayout->HandleBlockChangeL(cursor, 0, changes, 0);
+		end.UniversalTime();
+
+		TInt64 us = end.MicroSecondsFrom(start).Int64();
+		repeatsInThisPar ++;
+		TTFTimeStamp timestamp;
+		timestamp.iTime = us;
+		timestamp.iIteration = i;
+		User::LeaveIfError(aTimeStamps.Append(timestamp));
+		if(us > aSlowest)
+			{
+			aSlowest = us;
+			}
+		if (repeatsInThisPar > aRepeatsPerPara)
+			{
+			TChar paragraphDelimiter(0x2029);
+			aFormattingObjects.iRichText->InsertL(0, paragraphDelimiter);
+			repeatsInThisPar = 0;
+			}
+		}
+	}
+
+void MeasureCursorL(RArray<TTFTimeStamp>& aTimeStamps, TCursorPosition::TMovementType aType,
+	TFormattingObjects& aFormattingObjects, TInt64& aSlowest)
+	{
+	aTimeStamps.Close();
+	TTime start;
+	TTime end;
+	TInt lines = 0;
+	TCursorPosition::TMovementType move = aType;
+
+	while (move == aType)
+		{
+		lines++;
+		start.UniversalTime();
+		aFormattingObjects.iView->MoveCursorL(move, EFalse);
+		end.UniversalTime();
+		TInt64 us = end.MicroSecondsFrom(start).Int64();
+		TTFTimeStamp timestamp;
+		timestamp.iTime = us;
+		timestamp.iIteration = lines;
+		User::LeaveIfError(aTimeStamps.Append(timestamp));
+		if(us > aSlowest)
+			{
+			aSlowest = us;
+			}
+		const CTmTextLayout& tmLayout = aFormattingObjects.iLayout->TagmaTextLayout();
+		}
+	}
+
+void CreateFormattingObjectsLC(TFormattingObjects& aFormattingObjects)
+	{
+	TRect* displayRect = new(ELeave) TRect(0, 0, KDisplayWidth, KDisplayHeight);
+	CleanupStack::PushL(displayRect);
+	CParaFormatLayer* paraFormat = CParaFormatLayer::NewL();
+	CleanupStack::PushL(paraFormat);
+	CCharFormatLayer* charFormat = CCharFormatLayer::NewL();
+	CleanupStack::PushL(charFormat);
+	CRichText* text = CRichText::NewL(paraFormat, charFormat);
+	CleanupStack::PushL(text);
+	CTextLayout* layout = CTextLayout::NewL(text, displayRect->Width());
+	CleanupStack::PushL(layout);
+	CTestGraphicsDevice* device = CTestGraphicsDevice::NewL(displayRect->Size(), 0);
+	CleanupStack::PushL(device);
+	// Prevent the line array from using up the memory
+	device->LineArray().Disable();
+	CTextView* view = CTextView::NewL(layout, *displayRect,
+		device, device, 0, 0, 0);
+	CleanupStack::PushL(view);
+	// must disable flicker-free redraw or Form will try to use
+	// the test font with an off-screen (i.e. real) graphics context,
+	// which will panic.
+	view->DisableFlickerFreeRedraw();
+
+	aFormattingObjects.iDisplayRect = displayRect;
+	aFormattingObjects.iParFormat = paraFormat;
+	aFormattingObjects.iCharFormat = charFormat;
+	aFormattingObjects.iRichText = text;
+	aFormattingObjects.iLayout = layout;
+	aFormattingObjects.iDevice = device;
+	aFormattingObjects.iView = view;
+	}
+
+void DestroyFormattingObjects(TFormattingObjects& aFormattingObjects)
+	{
+	CleanupStack::PopAndDestroy(aFormattingObjects.iView);
+	CleanupStack::PopAndDestroy(aFormattingObjects.iDevice);
+	CleanupStack::PopAndDestroy(aFormattingObjects.iLayout);
+	CleanupStack::PopAndDestroy(aFormattingObjects.iRichText);
+	CleanupStack::PopAndDestroy(aFormattingObjects.iCharFormat);
+	CleanupStack::PopAndDestroy(aFormattingObjects.iParFormat);
+	CleanupStack::PopAndDestroy(aFormattingObjects.iDisplayRect);
+	}
+
+/**
+@SYMTestCaseID SYSLIB-FORMA-UT-1897
+@SYMTestCaseDesc Benchmarks scrolling text
+@SYMTestPriority High
+@SYMTestActions creates document and scrolls it
+@SYMTestExpectedResults The test must not fail or panic .
+@SYMDEF DEF092140, DEF092139
+*/
+void RunScrollingTestL(TInt aRepeats, TInt aRepeatsPerParagraph,
+	RArray<TTFTimeStamp>& aTimeStampsDown, RArray<TTFTimeStamp>& aTimeStampsUp,
+	TDocInfo& aDocInfo)
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-FORMA-UT-1897 "));
+	TInt docLength = KEnglish().Length() * aRepeats;
+	TInt paragraphs = aRepeats/aRepeatsPerParagraph;
+
+	TFormattingObjects o;
+	CreateFormattingObjectsLC(o);
+	o.iLayout->SetWrapWidth(KInsertDisplayWidth);
+	o.iLayout->SetAmountToFormat(CTextLayout::EFFormatBand);
+	SetTextL(*(o.iRichText), KEnglish, aRepeats, aRepeatsPerParagraph);
+
+	TTimeIntervalMicroSeconds opening = MeasureOpeningL(*(o.iView));
+	TInt64 slowest = 0;
+	MeasureCursorL(aTimeStampsDown, TCursorPosition::EFLineDown, o, slowest);
+	MeasureCursorL(aTimeStampsUp, TCursorPosition::EFLineUp, o, slowest);
+
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_Scrolling_Slowest_Doc_with_%d_characters_%d_paragraphs;microseconds: %Ld", docLength, paragraphs, slowest);
+
+	aDocInfo = GetSampleDocInfoL(o);
+	DestroyFormattingObjects(o);
+	}
+
+/**
+@SYMTestCaseID SYSLIB-FORMA-UT-1898
+@SYMTestCaseDesc Benchmarks inserting, deleting and formatting text
+@SYMTestPriority High
+@SYMTestActions creates documents in each language and performs edits and reformats
+@SYMTestExpectedResults The test must not fail or panic .
+@SYMDEF DEF092140, DEF092139
+*/
+void RunEnglishArabicJapaneseBenchmarksL(TFormattingObjects& aFormattingObjects)
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-FORMA-UT-1898 "));
+	SetTextL(*aFormattingObjects.iRichText, KEnglish, KEnglishRepeats, KEnglishRepeats);
+	TTimeIntervalMicroSeconds opening = MeasureOpeningL(*aFormattingObjects.iView);
+	TTimeIntervalMicroSeconds rmsCursorDown = MeasureRmsCursorDownL(*aFormattingObjects.iView);
+	TTimeIntervalMicroSeconds englishFormatting = MeasureFormattingL(*aFormattingObjects.iView);
+	TInt englishLines = NumberOfLines(*aFormattingObjects.iLayout);
+	SetTextL(*aFormattingObjects.iRichText, KArabic, KArabicRepeats, KArabicRepeats);
+	TTimeIntervalMicroSeconds arabicFormatting = MeasureFormattingL(*aFormattingObjects.iView);
+	TInt arabicLines = NumberOfLines(*aFormattingObjects.iLayout);
+	SetTextL(*aFormattingObjects.iRichText, KJapanese, KJapaneseRepeats, KJapaneseRepeats);
+	TTimeIntervalMicroSeconds japaneseFormatting = MeasureFormattingL(*aFormattingObjects.iView);
+	TInt japaneseLines = NumberOfLines(*aFormattingObjects.iLayout);
+
+	// Check that the results are fair
+	TInt minLines;
+	TInt maxLines;
+	if (arabicLines < englishLines)
+		{
+		minLines = arabicLines;
+		maxLines = englishLines;
+		}
+	else
+		{
+		minLines = englishLines;
+		maxLines = arabicLines;
+		}
+	if (japaneseLines < minLines)
+		minLines = japaneseLines;
+	else if (maxLines < japaneseLines)
+		maxLines = japaneseLines;
+
+	//Tests that the number of lines in each test is more or less balanced
+	test(maxLines * 100 <= minLines * 105);
+
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_OpeningLargeParagraph;microseconds: %d",
+		static_cast<TInt>(opening.Int64()));
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_RmsCursorDown;microseconds: %d",
+		static_cast<TInt>(rmsCursorDown.Int64()));
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormattingEnglish;microseconds: %d",
+		static_cast<TInt>(englishFormatting.Int64()));
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormattingArabic;microseconds: %d",
+		static_cast<TInt>(arabicFormatting.Int64()));
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormattingJapanese;microseconds: %d",
+		static_cast<TInt>(japaneseFormatting.Int64()));
+	}
+
+/**
+@SYMTestCaseID SYSLIB-FORMA-UT-1896
+@SYMTestCaseDesc Benchmarks inserting text from the beginning of a paragraph
+@SYMTestPriority High
+@SYMTestActions creates a large paragraph containg just one word and inserts text iteratively from
+the beginning
+@SYMTestExpectedResults The test must not fail or panic .
+@SYMDEF DEF092140, DEF092139
+*/
+void RunInsertTextTestsL(TInt aRepeats, TInt aRepeatsPerParagraph,
+	RArray<TTFTimeStamp>& aTimeStamps, TDocInfo& aDocInfo)
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-FORMA-UT-1896 "));
+	TFormattingObjects o;
+	CreateFormattingObjectsLC(o);
+	TInt64 slowest = 0;
+	o.iLayout->SetWrapWidth(KInsertDisplayWidth);
+	o.iLayout->SetAmountToFormat(CTextLayout::EFFormatBand);
+	MeasureInsertTextAtStartL(aRepeats, aRepeatsPerParagraph, aTimeStamps, o, slowest);
+	aDocInfo = GetSampleDocInfoL(o);
+
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_InsertText_Slowest;microseconds: %Ld", slowest);
+
+	DestroyFormattingObjects(o);
+	}
+
+/**
+@SYMTestCaseID SYSLIB-FORMA-UT-1895
+@SYMTestCaseDesc Benchmarks deleting text from the beginning of a paragraph
+@SYMTestPriority High
+@SYMTestActions creates a large paragraph containg just one word and deletes text iteratively from
+the beginning
+@SYMTestExpectedResults The test must not fail or panic .
+@SYMDEF DEF092140, DEF092139
+*/
+void RunDeleteTextFromStartTest(RArray<TTFTimeStamp>& aTimeStamps, TDocInfo& aDocInfo)
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-FORMA-UT-1895 "));
+	TFormattingObjects o;
+	CreateFormattingObjectsLC(o);
+	TInt64 slowest = 0;
+	o.iLayout->SetWrapWidth(KInsertDisplayWidth);
+	o.iLayout->SetAmountToFormat(CTextLayout::EFFormatBand);
+	RBuf bigbuf;
+	BigBufLC(bigbuf);
+	SetTextL(*o.iRichText, bigbuf, 1, 1);
+	TTimeIntervalMicroSeconds opening = MeasureOpeningL(*o.iView);
+
+	MeasureDeleteTextFromStartL(aTimeStamps, o, slowest);
+	aDocInfo = GetSampleDocInfoL(o);
+
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_DeleteText_Slowest;microseconds: %Ld", slowest);
+
+	CleanupStack::PopAndDestroy();//bigbuf
+	DestroyFormattingObjects(o);
+	}
+
+void GetFormattingBenchmarkL(TInt aNumberOfIterations, TInt& aNumberOfCharacters, TInt64& aNormalisedBenchmark)
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-FORMA-UT-1895 "));
+	TFormattingObjects o;
+	CreateFormattingObjectsLC(o);
+	o.iLayout->SetWrapWidth(KInsertDisplayWidth);
+	o.iLayout->SetAmountToFormat(CTextLayout::EFFormatBand);
+
+	SetTextL(*(o.iRichText), KEnglish, aNumberOfIterations, aNumberOfIterations);
+
+	TTimeIntervalMicroSeconds ignore = MeasureOpeningL(*(o.iView));
+	o.iView->SetDocPosL(o.iRichText->DocumentLength());
+	//make a global change
+	o.iLayout->SetWrapWidth(KChangedDisplayWidth);
+	//measure time to reformat for it
+	TTime start;
+	TTime end;
+	start.UniversalTime();
+	o.iView->HandleGlobalChangeL();
+	end.UniversalTime();
+
+	TTimeIntervalMicroSeconds formattingTime = end.MicroSecondsFrom(start);
+
+	aNumberOfCharacters = o.iRichText->DocumentLength();
+	aNormalisedBenchmark = formattingTime.Int64()/aNumberOfIterations;
+
+	DestroyFormattingObjects(o);
+	}
+
+/**
+@SYMTestCaseID SYSLIB-FORMA-UT-1894
+@SYMTestCaseDesc Benchmarks formatting text
+@SYMTestPriority High
+@SYMTestActions for a series of documents of increasing size consisting of a single paragraph,
+sets the cursor position to the end of the document, makes a global change and formats it.
+@SYMTestExpectedResults The test must not fail or panic. The increase in time taken should be
+roughly linear with the document size.
+@SYMDEF DEF095401
+*/
+void RunFormattingBenchmarksL()
+	{
+	test.Next(_L(" @SYMTestCaseID:SYSLIB-FORMA-UT-1894 "));
+	TInt numberOfCharacters = 0;
+	TInt numberOfIterations;
+	TInt64 normalisedBenchmark = 0;
+
+	numberOfIterations = 1;
+	GetFormattingBenchmarkL(numberOfIterations, numberOfCharacters, normalisedBenchmark);
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormatText;document contains %d characters: %Ld microseconds per iteration", numberOfCharacters, normalisedBenchmark);
+
+	numberOfIterations = 5;
+	GetFormattingBenchmarkL(numberOfIterations, numberOfCharacters, normalisedBenchmark);
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormatText;document contains %d characters: %Ld microseconds per iteration", numberOfCharacters, normalisedBenchmark);
+
+	numberOfIterations = 10;
+	GetFormattingBenchmarkL(numberOfIterations, numberOfCharacters, normalisedBenchmark);
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormatText;document contains %d characters: %Ld microseconds per iteration", numberOfCharacters, normalisedBenchmark);
+
+	numberOfIterations = 50;
+	GetFormattingBenchmarkL(numberOfIterations, numberOfCharacters, normalisedBenchmark);
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormatText;document contains %d characters: %Ld microseconds per iteration", numberOfCharacters, normalisedBenchmark);
+
+	numberOfIterations = 100;
+	GetFormattingBenchmarkL(numberOfIterations, numberOfCharacters, normalisedBenchmark);
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormatText;document contains %d characters: %Ld microseconds per iteration", numberOfCharacters, normalisedBenchmark);
+
+	numberOfIterations = 250;
+	GetFormattingBenchmarkL(numberOfIterations, numberOfCharacters, normalisedBenchmark);
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormatText;document contains %d characters: %Ld microseconds per iteration", numberOfCharacters, normalisedBenchmark);
+
+	numberOfIterations = 500;
+	GetFormattingBenchmarkL(numberOfIterations, numberOfCharacters, normalisedBenchmark);
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormatText;document contains %d characters: %Ld microseconds per iteration", numberOfCharacters, normalisedBenchmark);
+
+	numberOfIterations = 750;
+	GetFormattingBenchmarkL(numberOfIterations, numberOfCharacters, normalisedBenchmark);
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormatText;document contains %d characters: %Ld microseconds per iteration", numberOfCharacters, normalisedBenchmark);
+
+	numberOfIterations = 1000;
+	GetFormattingBenchmarkL(numberOfIterations, numberOfCharacters, normalisedBenchmark);
+	RDebug::Printf("PERFORMANCE: Syslibs;Form_FormatText;document contains %d characters: %Ld microseconds per iteration", numberOfCharacters, normalisedBenchmark);
+	}
+
+void RunBenchmarksL()
+	{
+	CActiveScheduler* scheduler = new(ELeave) CActiveScheduler;
+	CleanupStack::PushL(scheduler);
+	CActiveScheduler::Install(scheduler);
+
+	RunFormattingBenchmarksL();
+
+	TDocInfo docInfo;
+	RArray<TTFTimeStamp> timestampsDown;
+	RArray<TTFTimeStamp> timestampsUp;
+	CleanupClosePushL(timestampsDown);
+	CleanupClosePushL(timestampsUp);
+
+	RunDeleteTextFromStartTest(timestampsUp, docInfo);
+	WriteSampleDocInfo(docInfo, fileTimeStamps);
+	WriteTimeStampsL(KDeleteTextFromStart, timestampsUp);
+
+	RunInsertTextTestsL(KEnglishInsertRepeats, KEnglishInsertRepeats, timestampsUp, docInfo);
+	WriteSampleDocInfo(docInfo, fileTimeStamps);
+	WriteTimeStampsL(KInsertTextAtStart, timestampsUp);
+
+	RunScrollingTestL(KEnglishScrollRepeats, KEnglishScrollRepeats, timestampsDown, timestampsUp, docInfo);
+	WriteSampleDocInfo(docInfo, fileTimeStamps);
+	WriteTimeStampsL(KScrollingDown, timestampsDown);
+	WriteTimeStampsL(KScrollingUp, timestampsUp);
+
+	RunScrollingTestL(KEnglishScrollRepeats, KEnglishScrollRepeats/2, timestampsDown, timestampsUp, docInfo);
+	WriteSampleDocInfo(docInfo, fileTimeStamps);
+	WriteTimeStampsL(KScrollingDown, timestampsDown);
+	WriteTimeStampsL(KScrollingUp, timestampsUp);
+
+	RunScrollingTestL(KEnglishScrollRepeats, KEnglishScrollRepeats/10, timestampsDown, timestampsUp, docInfo);
+	WriteSampleDocInfo(docInfo, fileTimeStamps);
+	WriteTimeStampsL(KScrollingDown, timestampsDown);
+	WriteTimeStampsL(KScrollingUp, timestampsUp);
+
+	TFormattingObjects o;
+	CreateFormattingObjectsLC(o);
+	RunEnglishArabicJapaneseBenchmarksL(o);
+	DestroyFormattingObjects(o);
+
+	CleanupStack::PopAndDestroy(2);
+	CleanupStack::PopAndDestroy(scheduler);
+
+	}
+
+TInt E32Main()
+	{
+	test.Title();
+	test.Start(_L("Start Font/Bitmap Server"));
+	static CTrapCleanup* TrapCleanup = CTrapCleanup::New();
+	TInt error = RFbsSession::Connect();
+	if (error == KErrNotFound)
+		{
+		FbsStartup();
+		error = RFbsSession::Connect();
+		}
+	// Tests that FBServ actually starts
+	test(error == KErrNone);
+	error = fs.Connect();
+	test(error == KErrNone);
+
+	error = fileTimeStamps.Replace(fs, KLogTimeStampsName, EFileWrite);
+	RDebug::Printf("> fileTimeStamps.Replace %d", error);
+	test(error == KErrNone);
+
+	test.Next(_L("Run Benchmarks"));
+	TRAP(error, RunBenchmarksL());
+	// Tests that the Benchmarks did not run out of memory
+	// or otherwise leave
+	test(error == KErrNone);
+
+	fileTimeStamps.Close();
+	fs.Close();
+	RFbsSession::Disconnect();
+	delete TrapCleanup;
+	test.End();
+	test.Close();
+	return error;
+	}
+