The efficiency of erlang:universaltime_to_posixtime/1 and erlang:localtime_to_universaltime/1 functions

On linux

erlang:universaltime_to_posixtime(erlang:localtime_to_universaltime(Datetime))

slower than

Seconds = calendar:datetime_to_gregorian_seconds(Datetime), Seconds - 62167219200 - TimeZone * 3600

But on Windows, the first function is faster than the second, I looked at the source code, but I don’t know why the first function is slower

Erlang/OTP 22

4 Likes

Hello!

Can you post the code you use to benchmark? I don’t know why it behaves that way, but maybe I can find out.

3 Likes
-module(benchmark).

-export([t1/0,t2/0]).

t1() ->
    DateTime = {date(),time()},
    Fun = fun(_) -> erlang:universaltime_to_posixtime(erlang:localtime_to_universaltime(DateTime)) end,
    timer:tc(lists,foreach,[Fun,lists:seq(1, 1000000)]).

t2() ->
    DateTime = {date(),time()},
    TimeZone = 8,
    Fun = fun(_) -> calendar:datetime_to_gregorian_seconds(DateTime) - 62167219200 - TimeZone * 3600 end,
    timer:tc(lists,foreach,[Fun,lists:seq(1, 1000000)]).

On Windows

On Linux

The hardware of the two computers is quite different, we just need to see the test results

1 Like

When running the same benchmark on my windows and linux machines I get that t2 always is faster than t1.

I don’t know why the Windows machine that you run on is slower for t2.

2 Likes

Several of my friends ran the above benchmark and got results similar to mine. What I don’t understand is what makes t1 slower than t2

2 Likes

-module(benchmark).

-export([t1/0,t2/0, t3/0]).

t1() ->
   DateTime = {date(),time()},
   Fun = fun(_) -> erlang:universaltime_to_posixtime(DateTime) end,
   timer:tc(lists,foreach,[Fun,lists:seq(1, 1000000)]).

t3() ->
   DateTime = {date(),time()},
   Fun = fun(_) -> erlang:localtime_to_universaltime(DateTime) end,
   timer:tc(lists,foreach,[Fun,lists:seq(1, 1000000)]).

t2() ->
   DateTime = {date(),time()},
   TimeZone = 8,
   Fun = fun(_) -> calendar:datetime_to_gregorian_seconds(DateTime) - 62167219200 - TimeZone * 3600 end,
   timer:tc(lists,foreach,[Fun,lists:seq(1, 1000000)]).

  • I modified the test code and the test results are as follows

Blockquote
Erlang/OTP 25 [erts-13.0] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
Eshell V13.0 (abort with ^G)
1> benchmark:t1().
{27143,ok}
2> benchmark:t2().
{92850,ok}
3> benchmark:t3().
{1462271,ok}
4> os:cmd(" cat /etc/redhat-release").
“CentOS Linux release 8.5.2111\n”

this Centos is started in Docker
Judging by the test results , This is slow because of the function Erlang :localtime_to_universaltime/1 , I’ve been looking at some of the code and I don’t really understand why it’s so slow

2 Likes

Doing a conversion to localtime ends up as a call to localtime_r on Unix and FileTimeToLocalFileTime on Windows. Those calls can take a lot of time, especially compared to what datetime_to_gregorian_seconds does as that is just some math, while localtime_r may end up having to fetch what the current localtime is from the filesystem.

3 Likes

OK, thank you.

2 Likes

:grinning::grinning::grinning::grinning::grinning::grinning:

1 Like