C# & Unity: Change displayed Time with good performance on mobile Device - c#

Hey guys so I made this function which is called every frame.
- You think this is a good way to save performance or is there a better way?
private void GetCurrentTime()
{
m_TimeNow = System.Convert.ToString(System.DateTime.Now);
//If the previous time is not equals to the current time (without seconds = every minute)
if (m_PreTime != m_TimeNow.Remove(14))
{ //Change the Time displayed on the screen:
m_PreTime = m_TimeNow.Remove(14); //1. Copy current Time
m_Times = m_TimeNow.Split(' '); //2. Split to following parts
m_Time = m_Times[1].Remove(4); //3. Cutout seconds
m_Text_Time.text = m_Time + " " + m_Times[2]; //4. And change UI-Text: Time + AM/PM
}
}
This function is called every Frame and will be on a mobile android device.
Thanks!

I may see some improvements in your implementation. Here is what I can tell you from my own experience.
For a short answer, this his how I would write your function:
//
// Version 2
//
class TimerExample_V2 {
private DateTime _TimeNow = System.DateTime.Now;
private DateTime _PreTime = System.DateTime.Now;
private string _format = "t";
private string _cultureName = "en-US";
public TimerExample_V2() {
CultureInfo culture = new CultureInfo(_cultureName);
CultureInfo.CurrentCulture = culture;
}
public void UpdateCurrentTimeUI() {
_TimeNow = System.DateTime.Now;
if(_PreTime.Minute != _TimeNow.Minute) {
// Note: this case appear only once per minute.
_PreTime = System.DateTime.Now;
string newText = _TimeNow.ToString(_format);
//m_Text_Time.text = newText; // Update unity display
// I omit this display unity. (Same cost in both case)
}
}
Now for a longer answer with explanations:
Strings (Performance):
Strings are generally costly, specially when dealing with str processing and comparisons. For instance 'String.Remove(int)' creates a new string, which may call several costly methods such as malloc etc (Behind the scene). As far as I see, you keep all your dates as strings but could use only the raw format DateTime. A better approach would be to keep your data in the 'DateTime' format and convert them as a string only for the end user. (For instance, to update your Unity display). It is better to compare two int (ex: DateTime.ElapsedMilliseconds) than string (ex: m_PreTime != m_TimeNow.Remove(14))
Date format (Flexibility):
You would have several issues when dealing with different date formats. Your implementation expects "HH:mm AM / PM" format, but user may have a possibility to change the format (24h for instance).. Use the dark magic power that C# gives you. For instance, use the CultureInfo or the already implemented "DateTime.ToString(format)". (I just learned about 'CultureInfo'. There may be other ways. But as a general rule, see whether the language already has the feature you need).
Functions name:
This is a little thing, but try to have little functions that does what it says. In your case, from 'GetCurrentTime', we would expect a return value. This function actually update a display and return void. Something like 'UpdateTimeDisplay' is probably better.
Duplicate calls:
A second little thing: you have 2 calls to m_timeNow.Remove(14). You could create a new string once (From this function) and use this new string in both places.
Experiment (Measurements and validation)
Anyway, when dealing with performance, you have to measure, benchmark your code. (As an example, I first did an implementation for your GetCurrentTime and realized it wasn't actually better.). The following is a little experiemnt I created to show you some measurement. I'm not a C# shaman expert, nor a performance wizard expert but I hope my example is clear enought. I run the experiment on my laptop: (Intel i5-3320M CPU # 2.60GHz).
I have two implementations of your function. I run 10 000 times each function and print the execution time for each. (I omit the call to update the unity display, which is the same in both cases). My measurements show that your implementation took 45 ms, the other took 23 ms.
The second implementation sounds better. However, don't forget that I called 10 000 times the functions. In practice, with 60fps, you call the update 60 times per seconds. On my laptop, 60 iterations took 0 miliseconds for both.
There is another element to point out:
m_PreTime = m_TimeNow.Remove(14);
m_Times = m_TimeNow.Split(' ');
m_Time = m_Times[1].Remove(4);
These are kind of slow functions since dealing with strings creation. However, there are called only once per minute. As a matter of fack, I measured that, my implementation, when switching minute, uses the same amount of milliseconds as your. I may have failed my measurement or whatever, but maybe, once each minute, my function takes as much time as your. In all other cases, it is 'faster'. I may summerize this point using a quote:
"Solve for the most common case first, Not for the most generic"
(As far as I remember, this is a quote from the talk about optimization: https://www.youtube.com/watch?v=nXaxk27zwlk. Good talk btw)
Experiment (Source code)
So here is the full code of my terrible experiment:
using System;
using System.Globalization;
using System.Diagnostics;
// Instructions to compile (With mono)
// csc Program.cs
// mono Program.exe
class Program {
static void Main(string[] args) {
TimerExample_V1 timer_v1 = new TimerExample_V1();
TimerExample_V2 timer_v2 = new TimerExample_V2();
Stopwatch profiler;
int nbBenchLoops = 10000; // 10 000 times
float t1;
float t2;
// Profil version 1
profiler = Stopwatch.StartNew();
for(int k = 0; k < nbBenchLoops; ++k) {
timer_v1.UpdateCurrentTimeUI();
}
t1 = profiler.ElapsedMilliseconds;
// Profil version 2
profiler = Stopwatch.StartNew();
for(int k = 0; k < nbBenchLoops; ++k) {
timer_v2.UpdateCurrentTimeUI();
}
t2 = profiler.ElapsedMilliseconds;
// Print mesured times
Console.WriteLine("[SCOPE_PROFILER] [Version 1]: {0} ms", t1);
Console.WriteLine("[SCOPE_PROFILER] [Version 2]: {0} ms", t2);
}
}
//
// Version 1
//
class TimerExample_V1 {
private string m_TimeNow = System.Convert.ToString(System.DateTime.Now);
private string m_PreTime = System.Convert.ToString(System.DateTime.Now);
private string[] m_Times;
private string m_Time;
public void UpdateCurrentTimeUI() {
m_TimeNow = System.Convert.ToString(System.DateTime.Now);
if (m_PreTime != m_TimeNow.Remove(14)) {
// Note: this case appear only once per minute.
m_PreTime = m_TimeNow.Remove(14);
m_Times = m_TimeNow.Split(' ');
m_Time = m_Times[1].Remove(4);
string newText = m_Time + " " + m_Times[2];
//m_Text_Time.text = newText; // Update unity display
// I omit this display unity. (Same cost in both case)
}
}
}
//
// Version 2
//
class TimerExample_V2 {
private DateTime _TimeNow = System.DateTime.Now;
private DateTime _PreTime = System.DateTime.Now;
private string _format = "t";
private string _cultureName = "en-US";
public TimerExample_V2() {
CultureInfo culture = new CultureInfo(_cultureName);
CultureInfo.CurrentCulture = culture;
}
public void UpdateCurrentTimeUI() {
_TimeNow = System.DateTime.Now;
if(_PreTime.Minute != _TimeNow.Minute) {
// Note: this case appear only once per minute.
_PreTime = System.DateTime.Now;
string newText = _TimeNow.ToString(_format);
//m_Text_Time.text = newText; // Update unity display
// I omit this display unity. (Same cost in both case)
}
}
}
For further information about DateTime.ToString and CultureInfo, checkout the documentation:
CultureInfo C# Documentation
DateTime.ToString C# Documentation
Hope this will help :)

Related

I give input 1 to 9.. if the same input occurred 5 times with in 30 sec I want to print that

public class call
{
DateTime time = DateTime.Now;
public void check()
{
int count=0;
if(time < time.AddSeconds(30))
{
count ++;
if(count == 5)
{
Console.WriteLine(count);
}
}
public class Program
{
public static void Main(string[] args)
{
int input;
string sinput;
call one = new call();
call two = new call();
sinput = Console.ReadLine();
input = int.Parse(sinput);
do{
switch(input)
case 1: one.check();
break;
case 2: two.check();
break;
default: Console.WriteLine(":::");
break;
}while(input > 9)
}
}
}
I am new to programming...
I tried to print the number If it occurred 5 time within 30 sec...
I give input 1 to 9.. if the same input occurred 5 times with in 30 sec I want to print that..
You have a few bugs:
You'll probably want to replace:
if(time < time.AddSeconds(30))
With something the compares to the current time such as:
if(DateTime.Now < time.AddSeconds(30))
You are also incrementing count twice in your check method, not sure if that was intentional.
Inside of your do loop your switch body needs to be inside of {} and you probably should be reading a new input each time or doing something else to change the input or your loop will run forever.
You should also always validate user input. In this case if someone enters something other than a number your application will crash form this code:
sinput = Console.ReadLine();
input = int.Parse(sinput);
Instead lookup the int.TryParse method.
You create something like a class that logs the data for a certain input value (that is, stores the dates at which they are entered) and a class that binds those. Like, in pseudo-code:
class SingleInputLogger {
List<Date> dates
void addDate(Date date){
push date in dates
}
unsigned int currentSize(){
remove all entries from dates which are too old
return size of dates
}
}
class InputLogger {
Array<SingleInputLogger> singleInputLoggers of size 10 (or 9 if only 1..9, but then mind the offset)
//adds an input and also returns true if the input has a count of more than five
void addInput(int input){
singleInputLoggers[input].addDate(currentTime())
}
bool checkInput(int input){
if(singleInputLoggers[input].currentSize() >= 5){
return true
}
return false
}
Then the main routine becomes
InputLogger logger
while(get input){
logger.addInput(input)
if(logger.checkInput(input)){
display message "input " + input + " was entered more than five times in 30s"
}
}
(List was used to indicate a linked list in order to be able to efficiently remove front entries, Array was used to indicate a structure of static size for fast access)
Remember to let classes like this do the job for you. Try to use as less functions as possible and rather go with methods.
If someone has better names for those classes (I admit that my names are not that great), feel free to edit my answer.

Constantly update Datetime variable in C# console application

I am trying to run a piece of code on user defined time but the datetime variable stores the value of time when i hit run and does not update to check if the time has changed.
static void Main(string[] args)
{
Console.WriteLine("please enter the date in m/d/y h/m/s am/pm format ");
DateTime bombDate = Convert.ToDateTime(Console.ReadLine());
repeat:
//DateTime bombDate = "7/27/2016 4:13:16 AM";
DateTime now = DateTime.Now;
if (bombDate == now)
{
string _str = " this is a virus, you have been hit by a logic bomb ...";
while (true)
{
foreach (char c in _str)
{
SendKeys.SendWait(c.ToString());
Thread.Sleep(200);
}
Thread.Sleep(3000);
}
}
else {
goto repeat;
}
You can't match the two dates exactly, you're comparing the ticks here and the chances the two dates execute exactly at the same time Now matches the date is not that high. Since you're only specifying seconds from input then use this:
if ((bombDate - now).TotalSeconds < 0)
This matches the two dates even if there is it passed by up to less that 1 second.
Or you can just check if the needed time has passed:
if ((bombDate <= now))
I would post this as a comment but I can't.
Depending on what you're trying to do it might be worth to consider to write the program and just use a standard facility like the windows task scheduler to actually run it on specific conditions/times.
In addition goto is frowned up on by a lot of people for a good reason. Essentially you're creating a loop. Why not declare it as such? One possibility would be to use a loop which just counts the time (which is essentially what you're doing in your outer loop).
DateTime now = NULL;
while(bombDate != now){
now = DateTime.Now;
}
// Other Code beginning with string _str =
On way to circumvent the timing problem would be to add another sleep after your initial assignment/before the loop. That way you would be sure that some time passed between the successive calls of DateTime.Now. Going for a finer resolution like user3185569 suggested might be better though.

Console.Write(i) in each for or Console.write(Stringbuilder) at the end which one is better

Console.Write(i) in each for or Console.Write(StringBuilder) at the end: Which one is better?
I have two functions, the first one prints within the for loop and the other one is printing at the end.
public static void checkmethod1(int value, Checkevent text)
{
Stopwatch stopwatch2 = new Stopwatch();
stopwatch2.Start();
StringBuilder builder = new StringBuilder();
switch (text)
{
case Checkevent.odd:
for (int i = 1; i <= value; i = i + 2)
{
builder.Append(i).Append(" ");
}
break;
case Checkevent.even:
for (int i = 2; i <= value; i = i + 2)
{
builder.Append(i).Append(" ");
}
break;
}
stopwatch2.Stop();
Console.WriteLine(builder);
Console.WriteLine("{0}", stopwatch2.Elapsed);
}
Function 2:
public static void checkmethod3(int value, Checkevent text)
{
Stopwatch stopwatch2 = new Stopwatch();
stopwatch2.Start();
switch (text)
{
case Checkevent.odd:
for (int i = 1; i <= value; i = i + 2)
{
Console.Write(i);
}
break;
case Checkevent.even:
for (int i = 2; i <= value; i = i + 2)
{
Console.Write(i);
}
break;
}
stopwatch2.Stop();
Console.Write("{0}", stopwatch2.Elapsed);
}
In this particular scenario I will prefer StringBuilder as The loop is not taking significant time that could change the user experience. The StringBuilder in general require less memory and you will get better performance. As you each modification in string new string object is create but that is not the case with StringBuilder.
The first method executed the Console.Write only once but the second on will execute it the times for loop iterates. This will make the second one slow.
If you want to show user the text in console when you want user to see text as it appear like you are showing log to view the process flow then showing it once (with StringBuilder) may not give user chance to read it. In that case you would be write log as it is generated using Console.Write(string).
Deciding when to use string and when to use StringBuilder could become easy when you understand how both work. Their one of important behavior is given as under.
Using the StringBuilder Class in the .NET Framework
The String object is immutable. Every time you use one of the methods
in the System.String class, you create a new string object in memory,
which requires a new allocation of space for that new object. In
situations where you need to perform repeated modifications to a
string, the overhead associated with creating a new String object can
be costly. The System.Text.StringBuilder class can be used when you
want to modify a string without creating a new object. For example,
using the StringBuilder class can boost performance when concatenating
many strings together in a loop.
Edit
I test the above two method with three values 100, 10000 and 100000 and machine used has following specs
Operating System: Windows 7 Enterprise and CPU
Processor: Intel(R) Core (TM) i5-3570 CPU # 3.40 GHz 3.40 GHz
Installed memory (RAM): 8.00 GB
System Type: 64 bit Operating System
Value 100
Time with StringBuilder 00:00:00.0000184
Time without StringBuilder 00:00:00.0037037
Value 10000
Time with StringBuilder 00:00:00.0013233
Time without StringBuilder 00:00:00.2970272
Value 100000
Time with StringBuilder 00:00:00.0133015
Time without StringBuilder 00:00:02.5853375
In the first method where you used the StringBuilder the Console.Write is executed only once but in other case it is executed as many times as the loop iterations. This makes the second one slow. Comparing StringBuilder with string concatenation is not applicable here.

Assigning String Data to a Varaible

I'm new to programming in general, but I've thoroughly searched this and can't find anything that is related to this, but I admit it may be because I don't know 100% what to look for. So I apologize if this is redundant or extremely simple.
I'm working on an assignment in C# where we have to create a sentinel loop asking for a product # and quantity. With that, we make a calculation for cost and write all of that information to a private string variable.
In order to avoid academic dishonesty, I'll just ask about some code slightly different than the example.
private string test1;
public string Test1
{
get
{
return test1;
}
set
{
test1 = value;
}
}
}
...
Console.WriteLine("Enter a number");
int number1 Convert.ToInt32(Console.ReadLine());
int number2 = (number1*3);
This is the part that I can't figure out. I've tried it several ways:
test1 = ("{0}, {1}", number1, number2);
and
test = ("{0}, {1}", "number1", "number2");
as well as both of those iterations without parenthesis. I also can't get it to work even when "numer1" and "number2" are string variables.
Is it possible to assign this type of string data to a variable?
I'm not entirely sure what you edited, the reason your code isn't working is because your not calling String.Format. You can often ignore String.Format when you utilize a Console.WriteLine which has the functionality built into it.
Which is where I believe your confusion is occurring. To resolve your issue:
public class Example
{
private string example;
public Example(string example)
{
this.example = example;
}
public string Demo
{
get { return example; }
private set { example = value; }
}
}
The following class should be straight forward, we have our parameter which will assign a value to our Demo through the Constructor. So to store our value, as a String we would do the following:
var total = 0;
var number = 0;
if(int.TryParse(Console.ReadLine(), out number)
total = number * 3;
var example = new Example(String.Format("{0}, {1}", number, total));
Console.WriteLine(example.Demo);
So, the TryParse won't throw an exception if it fails to convert the user input. Then to format the String we utilize the String.Format. Then you can see such output by calling example.Demo.
Hopefully this clarifies your problem a bit.

Concatenate multiple strings versus String.Format [duplicate]

This question already has answers here:
String output: format or concat in C#?
(32 answers)
Closed 8 years ago.
Here is 2 methods which result the same:
public class MessageManager
{
public void SendMessage(string name, int count)
{
string message = "Hi " + name + ". I know you don't like cake, so I bought you " + count + " lollipops. Same thing, right?"; // No boxing. "count" was converted to string somehow.
//Console.WriteLine(message);
}
public void SendMessage2(string name, int count)
{
string message = String.Format("Hi {0}. I know you don't like cake, so I bought you {1} lollipops. Same thing, right?", name, count); // Boxing "name" and "count" + executing unnecessary code.
//Console.WriteLine(message);
}
}
So I guess the second method will be slower then first because of boxing and executing some additional code which inside String.Format() method.
I have tested them with following method:
public static class PerformanceTester
{
public static TimeSpan TestAction(Action<string, int> action)
{
Stopwatch timer = new Stopwatch();
timer.Start();
for (ushort i = 0; i < ushort.MaxValue; i++)
action("Alex", 1000);
timer.Stop();
return timer.Elapsed;
}
}
And here is the usage of it:
static void Main(string[] args)
{
MessageManager mm = new MessageManager();
TimeSpan ts_m1 = PerformanceTester.TestAction(new Action<string, int>(mm.SendMessage));
TimeSpan ts_m2 = PerformanceTester.TestAction(new Action<string, int>(mm.SendMessage2));
Console.WriteLine("First message took time: " + ts_m1.ToString());
Console.WriteLine("Second message took time: " + ts_m2.ToString());
Console.ReadKey();
}
Output with my Intel® Core™2 Duo Processor E8200 (DEBUG):
Output with my Intel® Core™2 Duo Processor E8200 (RELEASE):
I saw String.Format used almost everywhere (guides, blogs, tutorials etc.) but it is actually slower than simple string concatenation. I know when I talk about C# I must not care about performance, but the results in this example is too awesome.
The question is: "Is there any best practice where String.Format is actually better than concatenation of strings."
It's largely a matter of style. However, consider more complex formatting. For example you want to format a bunch of stuff:
var s = String.Format("{0,10:N2} {1,-20} {2:P2}", val, description, (val/100));
Or ...
var s = val.ToString("10:N2") + string.Format("{0,-20}", desc) + (val/100).ToString("P2");
I like the String.Format call there much better. It separates the formatting from the content in much the way that CSS separates the presentation from the HTML content. When I'm writing or examining code that formats output, I typically want to see the format at a glance. The actual values being formatted aren't relevant when I'm debugging a formatting issue.
With concatenation, I have to slog my way through the individual values to see what the format is for each item.
Finally, does performance really matter here? Most programs spend precious little time formatting their output. Optimizing the formatting code seems like a huge waste of time. Write whatever is easier to maintain and prove correct.
string.format is as the name suggest for formatting strings. you can take the format string and stick it in a resource or have it translated. it is not about performance and it is not about readability. simple string concatenation is ok if you do let's say less than 5. if you want to concatenate more strings and want to consider the performance - use StringBuilder.

Categories

Resources